Files
2026-04-20 18:42:48 +08:00

3.9 KiB
Raw Permalink Blame History

KernelRuntimeImport

English

KernelRuntimeImport 是教学性质的 Windows x64 内核驱动示例,用于展示如何在运行时通过函数名 Hash 解析 ntoskrnl.exe 的导出函数地址并调用。

概览

实现运行时动态导入API并调用:

  • 不直接在 PE 导入表中声明目标内核函数(IAT表不保存敏感函数,可以避免IAT Hook)。
  • 在运行时定位内核镜像基址。
  • 遍历导出表,对导出函数名做 Hash 比对。
  • 解析到目标函数地址后,再通过函数指针完成调用。

当前示例以 MmGetPhysicalAddress 为例,演示完整的解析与调用流程。

Features

  • 通过 __readmsr(0xC0000082) 辅助定位 ntoskrnl.exe 基址,不依赖常规内核导出查询 API。
  • 使用编译期字符串 Hash 宏 STRING_HASH(...) 生成目标导出名 Hash。
  • 通过遍历导出表并比较 Hash,在运行时解析目标函数地址。
  • 使用 CALL_ROUTINE(...) 宏将地址转换为目标函数签名并直接调用。
  • 示例代码短小,便于二次扩展为多个导出函数的运行时解析器。

drv_main.cpp 中的最小调用示例如下:

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);

上面的流程清楚说明了这个项目的核心功能:在驱动运行期间按 Hash 解析指定导出并直接调用,而不是通过静态导入项完成链接。

Supported Environment

目前仅在以下环境完成过测试:

系统版本 架构 状态
Windows 10 19044 x64 已测试
Windows 11 22H2 x64 已测试
Windows 11 24H2 x64 已测试
Windows 11 25H2 x64 已测试

说明:

  • 从实现方式来看,理论上应兼容大部分 Windows 10 / Windows 11 x64 版本。
  • 当前仓库只面向 x64 驱动场景,未验证 Win32、ARM 或 ARM64。

Build

当前构建环境如下:

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

构建步骤:

  1. 使用 Visual Studio 2017 打开 KernelRuntimeImport.sln。
  2. 确认已正确安装 WDK 10,并能使用 WindowsKernelModeDriver10.0 工具链。
  3. 将构建平台切换为 x64。
  4. 选择 Debug 或 Release 配置后执行编译。

说明:

  • 当前项目仅支持 x64 驱动使用。
  • 虽然工程文件中包含其他平台配置项,但当前实现和验证范围都以 x64 为准。

调试与警告

当导出函数解析失败时,当前示例会主动触发 DbgBreakPoint(),并返回 STATUS_PROCEDURE_NOT_FOUND:

if (MmGetPhysicalAddressAddr == nullptr)
{
	DbgBreakPoint();
	return STATUS_PROCEDURE_NOT_FOUND;
}

这意味着:

  • 请在调试器连接的测试环境或虚拟机中运行本示例。
  • 如果目标导出未解析成功,驱动会在 DriverEntry 阶段中断,便于立刻定位问题。

项目结构

  • KernelRuntimeImport/KernelRuntimeImport.h:Hash、函数指针调用宏以及导出接口声明。
  • KernelRuntimeImport/KernelRuntimeImport.cpp:内核基址定位与导出表遍历解析实现。
  • KernelRuntimeImport/drv_main.cpp:最小驱动入口与调用示例。

使用说明

这个仓库更适合作为研究和演示样例阅读:

  • 如果你想了解运行时导入的基本实现流程,可以从 DriverEntry 入口开始读。
  • 如果你想扩展为多个 API 的解析器,可以在现有 GetntoskrnlExportAddressByHash(...) 基础上继续封装。
  • 如果你想验证不同系统版本上的兼容性,建议在独立虚拟机中逐个测试。