【软件逆向-内核回调函数PsSetCreateProcessNotifyRoutine原理剖析】此文章归类为:软件逆向。
实验目的:研究通过PsSetCreateProcessNotifyRoutine注册的进程启停通知回调函数是如何被系统调用的。
废话不多说,直接开整~
1.通过windbg+Vmware搭建双机的调试环境,在windbg中对demo驱动中通过PsSetCreateProcessNotifyRoutine注册的回调函数设置断点。
2.加载驱动后,当断点命中时查看当前堆栈信息如下图:

从堆栈可知,我们的回调函数是通过nt!PspCallProcessNotifyRoutines+0x255调用的。那么通过IDA加载内核nt模块,查看此函数的伪代码如下:


我只截取关键的部分了,途中1,2,3标注的地方值得我们注意。
1说明函数ExReferenceCallBackBlock()要通过v20这个索引访问一个全局数组变量PspCreateProcessNotifyRoutine,3处做v20最大值的判断>=0x40就跳出循环,说明PspCreateProcessNotifyRoutine数组最大是0x40个,10进制就是64个,这告诉我们系统内部最多支持注册64个回调函数。
3.对ExReferenceCallBackBlock()进一步分析


1中取数组PspCreateProcessNotifyRoutine中具体的某一项,付给callBackEntry局部变量
2中对callBackEntry与0xFFFFFFFFFFFFFFF0进行&操作
最后返回与的结果给调用者。
4.回到PspCallThreadNotifyRoutines函数调用ExReferenceCallBackBlock继续分析

1中将结果放在寄存器rsi中
2中再对rsi+8,并将rsi+8所在地址的内容赋给rax
3中调用nt!guard_dispatch_icall(),该函数内部最终其实就是jmp rax
因此rax就是回调函数的真实地址。
那么我们归纳一下rax值是怎么来的,步骤如下:
1.rsi = PspCreateProcessNotifyRoutine[index]&0xFFFFFFFFFFFFFFF0
2.rax = rsi+8
得出解密算法是:PspCreateProcessNotifyRoutine[index]&0xFFFFFFFFFFFFFFF8
所以结论就是,每次进程启动函数或退出函数被调用时,系统内部就会对PspCreateProcessNotifyRoutine这个数组的内容不断地解码,然后依次调用。
谢谢大家不耐其烦的看到结尾~
更多【软件逆向-内核回调函数PsSetCreateProcessNotifyRoutine原理剖析】相关视频教程:www.yxfzedu.com