最近看到各位师傅疯狂蹂躏TX安全竞赛的题,文章写得好到让我泪流满面。不由的羡慕起来师傅们的技术...
ETW HOOK是一个经久不衰的话题了,本质上是微软的漏洞,再微软进行记录ETW时候系统调用的时候,被ETW相关组件拦截跑到记录的代码,因为涉及到的代码量实在太大,微软这里面老是会有一些函数指针的使用,从而可以把他替换成我们自己函数回调,而不会触发PG拦截系统调用(无法拦截直接内核NtXXX
)。
早期的ETW HOOK替换的一些HalPxx指针已经被PG监控
https://github.com/everdox/InfinityHook
到后来第二个版本的ETW,原理和EAC接管系统异常差不多,这一版本的也是再ETW HOOK的必经之路上面修改函数指针:
原理是EAC通过修改HalpStallCounter[0xE]
的这个位置,以及NtGlobalFlags
这个标志位。
HalpStallCounter[0xE] 函数原本是HalpTscQueryCounterOrdered
,修改这个之后,一些异常(包括kernel mode)就会走到这从而被EAC接管;
下图是发生异常时候的调用栈从windg可以看到,EAC
修改了HalpStallCounter
来进行接管异常
第二版的ETW Hook现在还可以用,但是用起来非常复杂,光是不同系统兼容、修栈就要耗费巨大精力。
因此这里参考国外的一个大佬文章,他提出了更新版本的ETW-HOOK,具体原理如下
WINDOWS的.data节一般是存放可以变的全局变量的,所谓的偷指针就是修改.data节区的指针。
而在这里,最好玩的是HalPrivateDispatchTable
,这个是windows 的ntoskenl.exe为了方便使用HAL的导出函数,把他们存放在统一的地方。而HAL,用到的地方肯定很多,ETW 正是如此。
我们来看一下系统调用ETW的调用路径
这里其实可以看到,call rax
其实就是正常的系统调用,而再进入ETW系统调用之前,他把原始的系统调用存放在了栈上,这就导致我们拦截到ETW的时候,可以修改栈上的位置,来进行HOOK Syscall。
进入这个函数
如果说之前无法定位,现在可以通过这个栈上面的magic number
来定位syscall的地址,从而替换了。
继续跟到EtwTraceSiloKernelEvent
里面,可以发现,无论参数怎么样,这个函数调用了EtwpLogKernelEvent
而EtwpLogKernelEvent
就是这次事件的主角,关键部分代码为
事实上,如果正常设置了ETW Logger syscall,就会走到这。这个函数的关键部分如下
这个地方HalPrivateDispatchTable.HalCollectPmcCounters(v21, (unsigned __int64 *)(v14 + 16));
就是可以替换的,也就是我们要替换HalPrivateDispatchTable
的HalCollectPmcCounters
.从而可以正常地接管syscall而不触发PG。
具体实现上其实很简单,就是调用ZwTraceControl
开启配置NT Kernel Logger
,这些代码都很简单,大概步骤是
偷指针,替换
配置Nt Kernel Logger,开启ETW
最麻烦的一步,如何设置PMCCounter开启,从而走到EtwpReserveWithPmcCounters
栈查找定位Syscall Routine
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-4-23 09:27
被Oxygen1a1编辑
,原因: 啦啦啦