文章导读
你是否好奇360安全卫士是如何高效管理众多Hook的?本文将深入解析360安全卫士的HOOK技术,带你了解其架构与实现,让你对HOOK技术有更深入的理解。
一、准备工作
首先,我们需要准备要Hook的系统服务的服务号ServiceIndex。对于导出的服务,我们可以通过获取Zw*函数地址后再取服务号的方法,而对于未导出的服务,则需要根据不同系统版本采用硬编码的方法。
接下来,我们需要准备缓冲区,存放原始服务例程地址、过滤开关、代理函数地址等,这些数据将被保存在ServiceFilterInfoTable中。HookPort.sys申请了一块很大的内存用于存放这些数据,其大小为0x5DDC=6007*4=(6006+1)*4,这是因为它实际上是一个结构体,包含多个表,每个表之间都有空隙。
此外,我们还需要准备缓冲区,存放过滤函数的地址和规则表,这些数据将被保存在FilterFunRuleTable中。这个缓冲区的实现虽然是在HookPort.sys中,但是它对外留出了这个接口,实际上却是由360SelfProtect.sys调用完成的。
二、KiFastCallEntry的Hook
目标KiFastCallEntry,但具体Hook在哪里最好?KiFastCallEntry是ring3经sysenter进入内核后的第一个必经之地,但是它的操作也很多,比如设置ds,es,fs段寄存器的值,从ETHREAD中取ServiceTable,判断ServiceIndex是否合法,然后从表中取出服务例程地址,从用户栈复制参数到内核栈,然后调用服务例程,调用完之后再做一点准备工作然后就由 KiServiceExit再飞回ring3。
360在KiFastCallEntry中的指令选择得非常好,它避免了太多的准备工作,都由系统准备好了,此时edi指向服务表的基址(KiServiceTable或W32pServiceTable),ebx是刚刚取出的原始服务例程的地址,eax是服务号,这时再做处理不是就很容易了嘛,重要的几个信息都有了。
三、代理函数如何处理?
每一个代理函数,都会首先调用一个CallFilterFunByIndex,调用时传入的第一个参数就是过滤函数在过滤函数表中的索引,也就是我们上一篇文章中所列出来的那些函数名称后面的索引。第二个参数则是栈中的参数数组,相当于一下把所有参数都传过去了。
CallFilterFunByIndex会先根据FilterFunRuleTable->IsFilterFunFilledReady判断该表是否已经准备好,根据传入的过滤函数的索引在FilterFunRuleTable表(也就是我们前面提到的第二张表)中查找对应的过滤函数,若过滤函数存在,就调用过滤函数,传入的参数同样有过滤函数索引和参数数组,在这个过滤函数中才真正实现了对参数的判断。
四、总结回顾
360安全卫士的HOOK架构设计非常好,易于修改,易于扩充,易于分工,无愧于优秀二字。单独写一个或几个函数的Hook,很多人都会,但是要实现这样一个产品级的优秀架构,就不是谁都能完成的了。
结束语
分析了360这样一个安全产品所使用的HOOK架构,让我收获颇多,也让大家领略了360安全卫士的技术魅力。我是陈景序,来自websoft网络软件专家(www.phpwebsoft.com),如果你对Web开发技术感兴趣,欢迎关注我们的网站了解更多内容。
