Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KernelRuntimeImport

中文文档

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.

Overview

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.

Features

  • Uses __readmsr(0xC0000082) to help locate the base address of ntoskrnl.exe without 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.

Supported Environment

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.

Build

The current build environment is:

  • Visual Studio 2017
  • WDK 10
  • x64 Kernel-Mode Driver

Build steps:

  1. Open KernelRuntimeImport.sln in Visual Studio 2017.
  2. Make sure WDK 10 is installed correctly and the WindowsKernelModeDriver10.0 toolset is available.
  3. Switch the build platform to x64.
  4. Build with either the Debug or Release configuration.

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.

Debugging and Warnings

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 DriverEntry so the issue can be diagnosed immediately.

Project Structure

  • 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.

Usage

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.

About

No description, website, or topics provided.

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages