之前发过一个求助贴,为什么在Windows10 64位系统通过PspCidTable的到的对象地址不是有效的。 求助帖链接
但是没有好兄弟来告诉我怎么回事。于是,它引起了我的好奇心,我便自己动手,逆PCHunter来解答我的困惑(感谢作者提供了这么好的工具)。
第一次发帖比较啰嗦,请耐心看,给各位看官比心♥。
PS:文末会提供所有的参考文章链接。
双机调试环境(虚拟机是W10 64位 1803),PCHunter,IDA
火绒 (提取PCHunter的驱动PCHunter64as.sys)。提取方法见下图
好的,准备工作到此结束,开干!!!
首先,我并不是用IDA远程调试内核的办法。是先通过IDA找到偏移,然后在windbg用 PCHunter64as.sys + 偏移 来确定地址。驱动文件拖入IDA,在DriverEntry里一顿观察(根据IRP_MJ_DEVICE_CONTROL=0x0E)找到与R3通信的函数及其偏移0x71434。
上虚拟机,启动PCHunter,看Windbg一气呵成。根据得到的偏移,在通信函数头部下断点。忽略第一次断点命中(弹出右键菜单),点击刷新第二次命中断点,OK,开始跟踪分析。
根据坛友 hjbfa 的分析,PCHunter有一套自己的通信协议[1]。但是这不是我们分析的重点,我们直接白嫖来用,一路跳过,来到关键的“CALL 寄存器”,就能在寄存器找到我们所关注的函数地址及其偏移0x431e4,转战IDA,根据偏移就能找到枚举进程的函数。然后经过反复的下断调试分析,观察内存里面进程信息的变化,一层一层的递进,就能找到最为关键的函数(我以为它在第0层,结果它在第2层)。
OK,经过一番努力来到最关键的函数,终于到了我们最喜欢的读汇编环节。对PspCidTable有过了解都应该知道,可以通过TableCode&(~3)判断是几级表[2]。最终都是在0级表处理,得到进程线程信息。所以分析,找到处理0级表的函数。(详情看IDA注释)
!!!看,我们发现了什么,获取的地址为什么无效,原来是因为经过简单的右移和与运算才是最终的对象地址。如果内核版本是Win8 则右移0x13,
再 &0xFFFFFFFFFFFFFFF0。如果内核版本是Win10,则右移0x10再与运算。就这样我的问题得到解决。马上自己计算验证一下。
!!!完美!!!
通过对PCHunter的动态调试与静态分析,终于解答了我的困惑。简简单单的右移运算,当初怎么没发现呢。果然实践出真知。当然,都已经到这一步了,怎么能不进一步深入了解PCHunter怎么检测进程的呢。简单分析发现,PCHunter从PspCidTable获取对象地址后,首先判断是线程,还是进程,然后分别处理。
所以仅仅对进程对象地址写0,还是能被PCHunter发现并标红。还需要对线程处理,修改线程指向的进程对象[3],才能完全躲过其检测。
贴一份我的隐藏进程三部曲(过PCHunter检测,但是线程指向改为system进程并不稳定,系统会蓝):
[1] hjbfa. 通过逆向PCHunter驱动学习64位windows内核之精准定位 https://bbs.pediy.com/thread-227207.htm
[2] xiaocaiccccc. 在Win7 x64通过PspCidTable枚举进程 https://blog.csdn.net/qq269813279/article/details/80679789?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1
[3] Justgoon. win7 32位进程隐藏(过PChunter检测) https://bbs.pediy.com/thread-221944.htm