本文参考:
剖析InfinityHook原理 掀起一场更激烈的攻与防恶战
Windows 10 19041版本的无限挂钩原理
Github项目InfinityHook
Github项目infhook19041
尝试过程:
为了技术储备,尝试在19041上进行稳定的InfinityHook
Windows19041 更新到最近的小版本 10.0.19041.388,下载对应的符号文件
直接编译大佬的项目Github项目infhook19041,运行,蓝屏,
调试发现
在没有获取到函数 KeQueryPerformanceCounter 中 mov rdi, cs:HalpPerformanceCounter 地址的情况下
访问了地址+3的位置去获取变量HalpPerformanceCounter所在的偏移
IDA 加上符号文件
简单修改了查找的特征码
再次编译,没有蓝屏,但是Hook没有生效
继续调试
发现是在被替换了的 keQueryPerformanceCounter 中,在栈中查找存储系统调用的地址,之前的偏移已经无效
最终效果:
Github项目infhook19041,这份代码大佬可能只是用来测试,所以卸载的不完整,系统不重启的情况下,停止再重启驱动后,获取到的 circularKernelContextLogger 的值为1,而本应该获取到circularKernelContextLogger的地址。
简单修改代码
声明一个变量来保存 GetCpuClock 的索引值,在将WMI_LOGGER_CONTEXT的GetCpuClock成员设置为1前,保存
std::uintptr_t OriginalGetCpuClock {};/* 原GetCpuClock的索引值 */
OriginalGetCpuClock = *reinterpret_cast<std::uint64_t*>(circularKernelContextLogger + Offsets::wmiGetCpuClock);
在卸载驱动时,还原 GetCpuClock
bool UnhookSystemCall() {
if (halpPerformanceCounter && halCounterQueryRoutine) {
*reinterpret_cast<std::uintptr_t*>(halpPerformanceCounter + Offsets::counterQueryRoutine) = halCounterQueryRoutine;
return true;
}
*reinterpret_cast<std::uint64_t*>(circularKernelContextLogger + Offsets::wmiGetCpuClock) = OriginalGetCpuClock;
if (!NT_SUCCESS(modifyCKCL(EtwStopLoggerCode, EVENT_TRACE_FLAG_SYSTEMCALL))) {
return false;
}
return false;
}
还发现了另外一个小问题,在事件跟踪控制中,ExAllocatePool 申请的内存,没有释放,简单改了下代码
NTSTATUS modifyCKCL(ETWTRACECONTROLCODE functionCode, std::uint32_t enableFlags) {
PCKCL_TRACE_PROPERTIES properties = reinterpret_cast<PCKCL_TRACE_PROPERTIES>(ExAllocatePool(NonPagedPool, PAGE_SIZE));
if (!properties)
return STATUS_INSUFFICIENT_RESOURCES;
memset(properties, 0, PAGE_SIZE);
properties->Wnode.BufferSize = PAGE_SIZE;
properties->Wnode.Guid = {0x54DEA73A, 0xED1F, 0x42A4, {0xAF, 0x71, 0x3E, 0x63, 0xD0, 0x56, 0xF1, 0x74}};
properties->Wnode.ClientContext = 0x1;
properties->Wnode.Flags = 0x20000;
properties->BufferSize = sizeof(std::uint32_t);
properties->MinimumBuffers = 2;
properties->MaximumBuffers = 2;
properties->LogFileMode = 0x400;
properties->EnableFlags = enableFlags;
properties->ProviderName = RTL_CONSTANT_STRING(L"Circular Kernel Context Logger");
std::uint32_t returnSize {};
NTSTATUS Status = ZwTraceControl(functionCode, properties, PAGE_SIZE, properties, PAGE_SIZE, reinterpret_cast<PULONG>(&returnSize));
ExFreePool(properties);
return Status;
}
小版本之间的兼容问题
存储系统调用的栈地址,我们可以通过遍历栈,替换所有储存了系统调用函数指针的地址。
halpPerformanceCounter可以通过加载符号文件,获取符号信息;
但是符号文件以国内的网络很多时候都会下载失败,除非我们提前下载好所有版本的符号文件,但是这样一来只能向前兼容,不能向后兼容。
看雪的大佬们,有什么好的解决方法?
附件:
1. 版本 10.0.19041.388 的 ntoskrnl.exe 与其符号文件
2. 修改后的Infinityhook
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2020-7-27 18:06
被随风行编辑
,原因: 新增了发现的问题