make InfinityHook great again
前言
在我折腾InfinityHook的时候我发现2004下系统没啥作用,原因是在2004系统上 WMI_LOGGER_CONTEXT->GetCpuClock已经不是rdtsc()函数了而是一个叫做 EtwpGetLoggerTimeStamp的函数
EtwpGetLoggerTimeStamp函数按照WMI_LOGGER_CONTEXT->GetCpuClock的值有如下操作:
大于3抛异常
等于3用rdtsc
等于2用off_140C00A30
等于1用KeQueryPerformanceCounter
等于0用RtlGetSystemTimePrecise
3,1,0都好说,但是这个2的off_140C00A30是什么鬼?
查看引用:
他是一个在data上,指向HalpTimerQueryHostPerformanceCounter的指针
(我虽然不知道他有什么作用,但是我非常震撼,因为他的引用就那几个…为什么还要用指针)
当在内核遇到不是那么热度高的指针的时候,我们可以搭档尝试一下hook,因为内核里面这些指针太多,pg是管不来的.所以我尝试改一下InfinityHook,让他能在2004上支持:
干活
1.获取指针地址
// off_140C009E0 pattern UCHAR pattern[] = "\x48\xcc\xcc\xcc\xcc\xcc\xcc\xE8\xcc\xcc\xcc\xcc\x83\xcc\xcc\x75\xcc\x38\xcc\xcc\xcc\xcc\xcc\x75\xcc\x48\xcc\xcc\xcc\xcc\xcc\xcc\x83\xB8\xcc\xcc\xcc\xcc\xcc\x0F\xcc\xcc\xcc\xcc\xcc"; NTSTATUS status = UtilScanSection(".text", (PCUCHAR)pattern, 0xCC, sizeof(pattern) - 1, (PVOID*)&PtrOff140C009E0); if (!NT_SUCCESS(status)) { kprintf("[DebugMessAge] off_140C009E0 not found! :( \n"); return false; } PtrOff140C009E0 = PtrOff140C009E0 + *(ULONG*)(PtrOff140C009E0 + 3) + 7;
2.修改这个指针
拥有指针后,记得将WMI_LOGGER_CONTEXT->GetCpuClock设置为2:
*reinterpret_cast<uintptr_t*>((uintptr_t)CkclWmiLoggerContext + OFFSET_WMI_LOGGER_CONTEXT_CPU_CYCLE_CLOCK) = 2;
然后就是修改为自己的地址:
*((ULONG64*)PtrOff140C009E0) = (ULONG64)HookHalpTimerQueryHostPerformanceCounter;
hook函数:
extern "C" __int64 __fastcall HookHalpTimerQueryHostPerformanceCounter(ULONG64 * pTime) { if (ExGetPreviousMode() != KernelMode) { //__debugbreak(); IfhpInternalGetCpuClock(); } return OldPtrOff140C009E0(pTime); }
IfhpInternalGetCpuClock里面,就是从stack上得到syscall地址,如果是自己的就改为原来的.
ps: 第一次知道kthread里面还有syscallnum这个字段….
static ULONG64 IfhpInternalGetCpuClock() { // // Extract the system call index (if you so desire). // PKTHREAD CurrentThread = (PKTHREAD)__readgsqword(OFFSET_KPCR_CURRENT_THREAD); unsigned int SystemCallIndex = *(unsigned int*)((uintptr_t)CurrentThread + OFFSET_KTHREAD_SYSTEM_CALL_NUMBER); PVOID* StackMax = (PVOID*)__readgsqword(OFFSET_KPCR_RSP_BASE); PVOID* StackFrame = (PVOID*)_AddressOfReturnAddress(); // // First walk backwards on the stack to find the 2 magic values. // for (PVOID* StackCurrent = StackMax; StackCurrent > StackFrame; --StackCurrent) { // // This is intentionally being read as 4-byte magic on an 8 // byte aligned boundary. // PULONG AsUlong = (PULONG)StackCurrent; if (*AsUlong != INFINITYHOOK_MAGIC_1) { continue; } // // If the first magic is set, check for the second magic. // --StackCurrent; PUSHORT AsShort = (PUSHORT)StackCurrent; if (*AsShort != INFINITYHOOK_MAGIC_2) { continue; } // // Now we reverse the direction of the stack walk. // for (; StackCurrent < StackMax; ++StackCurrent) { PULONGLONG AsUlonglong = (PULONGLONG)StackCurrent; if (!(PAGE_ALIGN(*AsUlonglong) >= SystemCallEntryPage && PAGE_ALIGN(*AsUlonglong) < (PVOID)((uintptr_t)SystemCallEntryPage + (PAGE_SIZE * 2)))) { continue; } // // If you want to "hook" this function, replace this stack memory // with a pointer to your own function. // void** SystemCallFunction = &StackCurrent[9]; if (IfhpCallback) { IfhpCallback(SystemCallIndex, SystemCallFunction); } break; } break; } return __rdtsc(); }
至此魔改完毕,关闭调试器打签名上虚拟机看看会不会被pg:
2004上至少两个小时内没有PG,但是测试了经过5个小时后,他蓝屏了
难道真的我们没办法让他great again了?
再次伟大!
在HalpTimerQueryHostPerformanceCounter中,往下看:
这两个指针其实就是得到系统时间..而且是唯一在HalpTimerQueryHostPerformanceCounter用到的指针…
如果之前的off_140C00A30是被PG监控的,这两个指针会不会被监控呢?能不能利用呢?
此外不仅这个off_140C00A30函数,还有几个在ETW上必call的函数指针,这些指针有没有被监控呢?
让我们跟踪这个HalpTimerQueryHostPerformanceCounter上的两个函数:
微软在栈上初始化了一个数组,然后依次给这个数组赋值,根据赋值的信息,我们可以逆向推导出函数名字:
(这个代码写的够烂的)
从而得知如下信息:
就从这个HvlGetQpcBias下手:
他会查询一个HvlpReferenceTscPage表,我们手动定位:
status = UtilScanSection(".text", (PCUCHAR)pattern_HvlpReferenceTscPage, 0xCC, sizeof(pattern_HvlpReferenceTscPage) - 1, (PVOID*)&HvlpReferenceTscPage); if (!NT_SUCCESS(status)) { kprintf("[DebugMessAge] HvlGetQpcBias not found! :( \n"); return false; } HvlpReferenceTscPage = HvlpReferenceTscPage + *(ULONG*)(HvlpReferenceTscPage + 3) + 7;
之后还是老套路,但是请记住修改我们的函数:
extern "C" __int64 HookHvlGetQpcBias() { //__debugbreak(); if (ExGetPreviousMode() != KernelMode) { IfhpInternalGetCpuClock(); } return *((ULONG64*)(*((ULONG64*)HvlpReferenceTscPage)) + 3); }
测试:
working,看看多久会蓝屏
暂时21: 00-0: 00没有蓝屏
21:00 – 第二天10:19
继续测试满24小时看看
扩展
再除此之外,不仅仅syscall,还有一些其他的异常信息、内存分配、文件创建等都会调用存在这些指针函数的函数,能不能做一些内核异常hook?
halv这部分的函数指针在kebugcheck2中也有而且也被调用了,是不是可以从蓝屏中恢复系统?
等你来回答了,因为我时间不多
github:
https://github.com/huoji120/MakeInfinityHookGreatAgain
修正,也有人做了差不多的,不过他是HalpPerformanceCounter:
https://www.anquanke.com/post/id/206288
这洞留不久,估计再过几天就完全完蛋蛋了
来源:freebuf.com 2021-06-28 18:19:11 by: huoji120
请登录后发表评论
注册