Kernel driver that hijacks a microsoft signed driver (win32kbase.sys) by swapping a pointer stored in its .data section making it point to our manually mapped handler.
This is a proof-of-concept project I developed in 2021 to teach myself the fundamentals of Windows kernel memory and driver internals. The primary goal was purely educational.
This code is not intended for production use. It is provided as-is to demonstrate the concepts learned.
This repository contains two components:
/kernel-driver: The kernel-mode driver payload, designed to be manually mapped./usermode-tester: A user-mode console application that calls the legitimate (hooked) Windows API to trigger and test the kernel hook.
This is not a traditional WDM driver. The code is designed to be manually mapped into the kernel's address space, not loaded via NtLoadDriver.
Due to this "shellcode-like" design:
- It lacks critical objects such as
PDRIVER_OBJECTorPREGISTRY_PATH. - It does not have a
DriverUnloadroutine. Cleanup (restoring the hook) must be handled by the loader or an external component. - The project's entry point is simply the beginning of the mapped code block.
The objective of this project was to explore advanced function hooking techniques from kernel-mode.
Instead of common IRP hooking used to hijack legitimate IOCTL drivers, this driver targets the .data section of a legitimate, loaded driver. It identifies a specific function pointer stored in that section and atomically swaps it, redirecting the pointer to a custom-defined function within this driver.
The result is that when a user-mode process triggers the legitimate driver's functionality, the legitimate driver itself unwittlingly calls our hooked function, effectively intercepting the execution flow.
This project was a foundational learning experience in Windows Internals. The key concepts I explored were:
- Kernel Memory Manipulation: Programmatically finding a loaded driver's base address and scanning its memory sections (like
.data). - Function Hooking: Implementing a function hook by overwriting a function pointer, rather than modifying code (like .text section inline hooking).
- Memory Protection (WP): Understanding and bypassing kernel memory protections (like Write Protect bits in the CR0 register) to patch read-only sections.
- Manual Mapping Concepts: Designing code to be position-independent and to function without the standard WDM boilerplate.
- Kernel Debugging: Using
WinDbgandDbgViewto debug memory overwrites and kernel-mode execution flow.
- Manual Import Resolution: Resolves all required kernel functions (like PsLookupProcessByProcessId) at runtime to avoid listing them in the driver's Import Address Table (IAT).
- Hashed & Encrypted Imports: Function names are not stored as plain text. They are hashed and encrypted to further obfuscate the driver's intent.
- String Obfuscation: All strings are XOR-encrypted to prevent static analysis.
- Basic Anti-Stackwalking: Implements a technique (via APC delivery) to protect against basic thread stack-walking.
- CR3 Resolution: Manually resolves a target process's CR3 (page table directory) by walking the PML4 tables.
- Physical Memory Access: Includes code for reading physical memory.
This project was inspired by the challenge of understanding complex Windows Internals. Feel free to explore the code.