KernelRuntimeImport is a minimal Windows x64 kernel driver sample that demonstrates how to resolve and call exported functions from ntoskrnl.exe at runtime through function name hashing.
This project demonstrates dynamic API importing and invocation at runtime:
- The target kernel function is not declared directly in the PE import table, so the IAT does not store the sensitive function and IAT hooks can be avoided.
- The kernel image base is located at runtime.
- The export table is traversed and export names are matched by hash.
- After resolving the target function address, the function is invoked through a function pointer.
The current sample uses MmGetPhysicalAddress as an example to show the complete resolution and invocation flow.
- Uses
__readmsr(0xC0000082)to help locate the base address ofntoskrnl.exewithout relying on conventional kernel export lookup APIs. - Uses the compile-time string hash macro
STRING_HASH(...)to generate the hash of the target export name. - Resolves the target function address at runtime by traversing the export table and comparing hashes.
- Uses the
CALL_ROUTINE(...)macro to cast the resolved address to the target function signature and invoke it directly. - Keeps the sample compact and easy to extend into a runtime resolver for multiple exported functions.
The minimal invocation example in drv_main.cpp is shown below:
constexpr ULONG MmGetPhysicalAddressHash = STRING_HASH("MmGetPhysicalAddress");
PVOID MmGetPhysicalAddressAddr = GetntoskrnlExportAddressByHash(MmGetPhysicalAddressHash);
if (MmGetPhysicalAddressAddr == nullptr)
{
DbgBreakPoint();
return STATUS_PROCEDURE_NOT_FOUND;
}
ULONG Num = 0x12345678;
PHYSICAL_ADDRESS PhyAddr = CALL_ROUTINE(
MmGetPhysicalAddressAddr,
ROUTINE_TYPE(PHYSICAL_ADDRESS, _In_ PVOID),
&Num);
UNREFERENCED_PARAMETER(PhyAddr);This flow clearly shows the core purpose of the project: resolve a specified export by hash during driver runtime and call it directly, instead of linking through a static import entry.
The project has currently been tested only in the following environments:
| OS Version | Architecture | Status |
|---|---|---|
| Windows 10 19044 | x64 | Tested |
| Windows 11 22H2 | x64 | Tested |
| Windows 11 24H2 | x64 | Tested |
| Windows 11 25H2 | x64 | Tested |
Notes:
- Based on the implementation approach, it should theoretically be compatible with most Windows 10 / Windows 11 x64 versions.
- The current repository targets x64 driver scenarios only and has not been validated on Win32, ARM, or ARM64.
The current build environment is:
- Visual Studio 2017
- WDK 10
- x64 Kernel-Mode Driver
Build steps:
- Open
KernelRuntimeImport.slnin Visual Studio 2017. - Make sure WDK 10 is installed correctly and the
WindowsKernelModeDriver10.0toolset is available. - Switch the build platform to
x64. - Build with either the
DebugorReleaseconfiguration.
Notes:
- The current project supports x64 drivers only.
- Although the project file contains other platform configurations, the implementation and validation scope currently target x64 only.
When export resolution fails, the current sample actively triggers DbgBreakPoint() and returns STATUS_PROCEDURE_NOT_FOUND:
if (MmGetPhysicalAddressAddr == nullptr)
{
DbgBreakPoint();
return STATUS_PROCEDURE_NOT_FOUND;
}This means:
- Run this sample in a test environment or virtual machine with a debugger attached.
- If the target export cannot be resolved successfully, the driver will break in
DriverEntryso the issue can be diagnosed immediately.
KernelRuntimeImport/KernelRuntimeImport.h: Hash helpers, function pointer invocation macros, and exported interface declarations.KernelRuntimeImport/KernelRuntimeImport.cpp: Kernel base discovery and export table traversal / resolution logic.KernelRuntimeImport/drv_main.cpp: Minimal driver entry and invocation example.
This repository is better suited as a research and demonstration sample:
- If you want to understand the basic runtime import flow, start reading from
DriverEntry. - If you want to extend it into a resolver for multiple APIs, continue building on top of
GetntoskrnlExportAddressByHash(...). - If you want to validate compatibility across different system versions, test them one by one in isolated virtual machines.