| name | Windows Driver Exploit |
| description | Windows kernel driver exploitation — IOCTL vulnerabilities, pool overflow, token escalation |
| tags | ["windows","driver","kernel","exploit","ioctl","privilege-escalation"] |
Task: Windows Kernel Driver Exploitation. Exploit vulnerabilities in Windows drivers for privilege escalation.
Phase 1: Driver Reconnaissance
Identify Attack Surface
1. Find DriverEntry:
- Entry point function
- Sets up DriverObject->MajorFunction
2. Extract Device Names:
- \Device\DriverName
- \DosDevices\DriverName
- Symbolic links
3. Map IOCTL Handlers:
- IRP_MJ_DEVICE_CONTROL dispatch
- Switch statement on IoControlCode
- Document each IOCTL code
IOCTL Code Decoding
CTL_CODE(DeviceType, Function, Method, Access)
DeviceType: 0x0000 - 0xFFFF
Function: 0x0000 - 0x07FF (0x800-0xFFF for Microsoft)
Method: METHOD_BUFFERED (0)
METHOD_IN_DIRECT (1)
METHOD_OUT_DIRECT (2)
METHOD_NEITHER (3)
Access: FILE_ANY_ACCESS (0)
FILE_READ_ACCESS (1)
FILE_WRITE_ACCESS (2)
Phase 2: Vulnerability Classes
METHOD_NEITHER IOCTLs (High Risk)
Pattern: No buffer validation
- User buffers passed directly to kernel
- No ProbeForRead/ProbeForWrite
- Raw pointer access from usermode
Exploit:
1. Pass kernel addresses as buffers
2. Read/write kernel memory
3. Build arbitrary R/W primitive
Pool Overflow
Pattern: ExAllocatePoolWithTag + unchecked copy
- Size calculation issues
- Integer overflow in allocation
- Overflow into adjacent objects
Targets:
- IOCTL handlers
- Device property handlers
- Custom allocation routines
Stack Buffer Overflow
Pattern: Fixed stack buffer + user copy
- char buffer[N]; memcpy(buffer, user, size);
- No size checking
- Classic stack overflow in kernel
Bypass:
- SMEP: Can't execute user shellcode
- Use ROP chain instead
- Stack pivot to user stack
Use-After-Free
Pattern: Dereference after cleanup
- ObDereferenceObject
- Use without revalidation
- Double-free scenarios
Exploit:
1. Free kernel object
2. Realloc with controlled data
3. Corrupt vtable/function pointers
4. Trigger callback
Race Condition (TOCTOU)
Pattern: Check → Use gap
- Time-of-check to time-of-use
- Non-atomic operations
- Lock-free code paths
Exploit:
- Multi-threaded race
- Win between check and use
- Corrupt kernel state
Missing Validation
Pattern: No bounds checking
- Arbitrary pointer dereference
- Missing ProbeForXxx calls
- No CAP checks
Impact:
- Kernel memory disclosure
- Arbitrary kernel R/W
- Privilege escalation
Phase 3: Exploit Primitives
Arbitrary Read (Information Leak)
HANDLE drv = CreateFile("\\.\\VulnDriver", ...);
DWORD bytes;
ReadRequest req;
req.Address = 0xFFFF800123400000;
DeviceIoControl(drv, IOCTL_READ, &req, sizeof(req),
&output, sizeof(output), &bytes, NULL);
Arbitrary Write
WriteRequest req;
req.Address = target_address;
req.Value = 0x12345678;
req.Size = 8;
DeviceIoControl(drv, IOCTL_WRITE, &req, sizeof(req),
NULL, 0, &bytes, NULL);
Pool Overflow Grooming
1. Spray pool with controlled objects
- Event, Semaphore, Mutant objects
- Use predictable allocation tags
- Control object layout
2. Trigger overflow
- Overflow adjacent object
- Corrupt critical pointers
- vtable, function pointers
3. Trigger corrupted object
- Call virtual function
- Execute controlled code
Phase 4: Privilege Escalation
Token Stealing (Windows 10/11)
1. Build arbitrary read primitive
2. Find current process EPROCESS
3. Find SYSTEM process EPROCESS
4. Copy SYSTEM token to current process
Offsets (version-dependent):
- EPROCESS.Token: 0x208 + 0x8 * (ImageFileName offset)
- EPROCESS.UniqueProcessId: 0x2e8
- EPROCESS.ActiveProcessLinks: 0x2f0
- EPROCESS.ImageFileName: 0x450
Steps:
1. PsInitialSystemProcess -> SYSTEM EPROCESS
2. ActiveProcessLinks.Flink -> Walk process list
3. Find current process by PID
4. Copy Token pointer
GDI BitMap Exploit
1. Create BitMap objects (kernel pool)
2. Use UAF to corrupt BitMap header
3. BitMap bits point to kernel address
4. Write via SetBitmapBits
5. Read via GetBitmapBits
Target: EPROCESS token
Palette Object Exploit
1. Create palette objects
2. Free and realloc with controlled data
3. Corrupt palette function pointers
4. Trigger callback for code execution
Phase 5: Mitigation Bypass
SMEP Bypass (CR4 bit 20)
Method 1: ROP to disable SMEP
- Find gadget: mov cr4, rax; ret
- Clear bit 20 (0x100000)
- Execute user shellcode
Method 2: Stack pivot
- ROP to user stack
- Execute shellcode from userland
- No kernel shellcode needed
Method 3: Kernel-only ROP
- Full ROP chain in kernel
- Use existing kernel code
- No shellcode at all
SMAP Bypass (CR4 bit 21)
Method 1: Disable via CR4
- Same as SMEP bypass
- Clear bit 21 (0x200000)
Method 2: Data-only attack
- Don't access user memory
- All operations in kernel
- Use kernel APIs
KASLR Bypass
Method 1: Information leak
- Uninitialized kernel memory
- IOCTL info leak
- Kernel heap disclosure
Method 2: Non-randomized addresses
- ntoskrnl.exe base (partially)
- Driver bases (if not ASLR)
Method 3: Guessing
- Low randomization bits
- Brute force on 32-bit
CFG/Shadow Stack
Bypass:
- Find compatible gadgets
- Use ROP with valid targets
- Indirect calls via CFG-valid addresses
Phase 6: Exploit Template
#include <windows.h>
#include <stdio.h>
#define IOCTL_READ CTL_CODE(0x8000, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_WRITE CTL_CODE(0x8000, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct _READ_REQUEST {
ULONG64 Address;
ULONG64 Size;
PVOID Buffer;
} READ_REQUEST;
typedef struct _WRITE_REQUEST {
ULONG64 Address;
ULONG64 Size;
ULONG64 Value;
} WRITE_REQUEST;
int main() {
HANDLE drv = CreateFile("\\\\.\\VulnDriver",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (drv == INVALID_HANDLE_VALUE) {
printf("Failed to open driver\n");
return 1;
}
DWORD bytes;
READ_REQUEST read_req = {0};
read_req.Address = 0xFFFF800000000000;
read_req.Size = 0x1000;
BYTE leak_buffer[0x1000];
DeviceIoControl(drv, IOCTL_READ, &read_req, sizeof(read_req),
leak_buffer, sizeof(leak_buffer), &bytes, NULL);
WRITE_REQUEST write_req = {0};
write_req.Address = eprocess_token_offset;
write_req.Value = system_token_value;
DeviceIoControl(drv, IOCTL_WRITE, &write_req, sizeof(write_req),
NULL, 0, &bytes, NULL);
system("cmd.exe");
CloseHandle(drv);
return 0;
}
Phase 7: Testing
Kernel Debugging Setup
1. Enable debug mode:
bcdedit /debug on
bcdedit /dbgsettings serial debugport:1 baudrate:115200
2. Connect WinDbg:
windbg -k com:port=COM1,baud=115200
3. Useful commands:
!process 0 0 - List all processes
dt nt!_EPROCESS - Show EPROCESS structure
!token - Show process token
dps kernel_base+Lxxx - Dump kernel symbols
Version-Specific Offsets
Use WinDbg to find offsets:
1. !process 0 0 -> Find System process
2. dt nt!_EPROCESS <addr> -> Dump structure
3. Find Token offset
4. Find ActiveProcessLinks offset
5. Update exploit with correct offsets
Final Report
[WINDOWS DRIVER EXPLOIT]
Driver: \Device\VulnerableDriver
IOCTL: 0x222003 (METHOD_NEITHER)
[VULNERABILITY]
Type: Missing validation in IOCTL handler
Impact: Arbitrary kernel read/write
Severity: CRITICAL
[EXPLOITATION]
1. Info leak: Kernel base @ 0xFFFFF80012340000
2. Primitive: Arbitrary R/W via METHOD_NEITHER
3. Target: Current process EPROCESS
4. Token: Copy SYSTEM token
5. Result: SYSTEM privileges
[BYPASSES]
- SMEP: CR4 modification via ROP
- SMAP: Disabled in same ROP
- KASLR: Info leak via IOCTL
[POC]
- Open: \\.\VulnDriver
- IOCTL: 0x222003 with kernel addresses
- Result: SYSTEM shell
Severity: CRITICAL
Affected: All Windows versions with this driver
Tools
- WinDbg: Kernel debugging
- IDA Pro/Ghidra: Driver RE
- Windows Driver Kit: Headers
- OSR Online: Driver resources