剖析InfinityHook原理 掀起一场更激烈的攻与防恶战
为了技术储备,尝试在19041上进行稳定的InfinityHook
Windows19041 更新到最近的小版本 10.0.19041.388,下载对应的符号文件
直接编译大佬的项目Github项目infhook19041,运行,蓝屏,
调试发现
在没有获取到函数 KeQueryPerformanceCounter 中 mov rdi, cs:HalpPerformanceCounter 地址的情况下
访问了地址+3的位置去获取变量HalpPerformanceCounter所在的偏移
IDA 加上符号文件
简单修改了查找的特征码
再次编译,没有蓝屏,但是Hook没有生效
继续调试
发现是在被替换了的 keQueryPerformanceCounter 中,在栈中查找存储系统调用的地址,之前的偏移已经无效
最终效果:
声明一个变量来保存 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 与其符号文件
[公告]看雪论坛2020激励机制上线了!发帖不减雪币了!如何获得积分快速升级?
最后于 42分钟前 被随风行编辑 ,原因: 新增了发现的问题