原始出处:http://www.rootkit.com/newsread.php?newsid=922
信息来源:0GiNr,零下安全 信心无限
文章作者:xrayn
译文作者:wangweinoo1
译者声明:本译版首发于0GiNr,后由wangweinoo1极小规模修改后发于EST,转载请保持信息完整
文章目录:
0.前言(Preface)by wangweinoo1
1.目标(Purpose)
2.通过修改驱动导入表来隐藏SSDT HOOK(Hide SSDT hooks by modifying the EAT of loaded drivers)
3.通过修改KTHREAD结构来隐藏SSDT HOOK(Hide SSDT hooks by manipulating the KTHREAD structure)
4.试验结果(Results)
5.结论(Conclusion)
6.作者(Developers)
7.参考资料(References)
0.前言(preface)
哈哈,此乃wangweinoo1自己写的(译员也来干这非本份滴事。。)这是发表一点自己的感受
不得不说,现在KeServiceDescriptorTable都用的快泛滥鸟,俗话曰,物极必反,各种反Rookit一批一批出现,检测SSDT HOOK也成了小菜一碟,就算按这种小白也懂得拿Icesword来来检查SSDT HOOK鸟^_^。那么,隐藏我们的HOOK也成了一个问题,xrayn在此提出了两种方法——modifying the EAT of loaded driver和manipulating the KTHREAD structure,估计大家还有其他方法吧,拿来贡献吧!(对地下表示BS。。。。),OK,大家自己看吧!
1.目标(Purpose)
许多商业产品和rookits通过改变内核SSDT里函数指针来完全控制系统。但遗憾的是,目前没有技术来隐藏这些HOOK(与本文主旨相矛盾 ,另据FlowerCode介绍AVZ已使用本文所说第二种方法)这篇短文描述了隐藏SSDT HOOK且不被当前的的反rookit工具检查出的两种方法。
2.通过修改驱动导入表来隐藏SSDT HOOK(Hide SSDT hooks by modifying the EAT of loaded drivers)
wangweinoo1注:这个标题其实有点不准确,实为给SSDT做备份,然后改指针
我们要做的第一步是给还未被修改的SSDT表做备份(唔,用处在后面会讲)。然后用PsSetLoadImageNotifyRoutine()做一个回调,这个回调是用来分析新加载驱动的IAT(导入表),如果发现了KeServiceDescriptorTable,那么修改指针使其指向我们前面做的SSDT备份(这就是前面做备份的用处)。这时,NtReadFile()、NtCreateFile()和NtMapViewOfSection()就可以由修改真实的SSDT而被HOOK了。HOOK这三个函数的目的是确保驱动(虾米驱动捏,呵呵)难以获得真实SSDT指针(原文为pointer,其实我觉得译为地址也许会更好?)
wangweinoo1简评:很好,很暴力。就是方法有点猥琐,不过尚为常规思路
3.通过修改KTHREAD结构来隐藏SSDT HOOK(Hide SSDT hooks by manipulating the KTHREAD structure)
第二个技术与上面第一个技术大致上相同,同样是内核结构的备份,不过这次是要改变每个线程的SSDT指针了。如果你反编译KiSystemService的话,你将会看到它其实是通过每个线程的控制块里ServiceTable指针来获得函数指针的(总感觉这句话译起来有点困难。。。)。ServiceTable pointer是由KeInitThread()初始化,PsConvertToGuiThread()负责构建。通过判断线程的类型来了解这个指针是指向SSDT还是SSDT-Shadow。Shadow里包含了GUIs所要需用的函数的指针,所以PsConvertToGuiThread()自然会改变ServiceTable的指针使其指向SSDT-Shadow。下面,你可以看到KTHREAD的结构:
kd> dt !_kthread
nt!_KTHREAD
[...]
+0x0e0 ServiceTable : Ptr32 Void
[...]
修改KTHREAD结构以隐藏SSDT HOOk,那么SSDT和Shadow SSDT的备份也该随之而建立。下一步就是修改SSDT或者Shadow SSDT来完全控制系统。现在,我们还需要修改内核代码使PsConvertToGuiThread()和KeInitThread()所对应的ServiceTable指针能够正确的指向我们的备份,这样以后所有枚举的线程里面的ServiceTable结构指针都就改了。
我已用RootkitUnhooker, GMER, SVV等反Rookit来测试我们隐藏HOOK的效果,以上工具均没有检测出内核代码和KTHREAD结构的修改。
4.试验结果(Results)
这个demo展示了通过改变线程ServiceTable指针来HOOK NtOpenProcess()以加载一个驱动的例子。在HOOK后,我们使用反Rootkit软件来检测,我们看到,这些工具并没有发觉SSDT或SSDT-Shadow被修改。换句话说,我们的实验成功的获得了令人满意的效果。(原文下面的这个链接已失效)
http://rapidshare.com/files/161590863/hidessdthooks.avi.html
5.结论(Conclusion)
我们的实验已经表明隐藏SSDT HOOK的存在,尽管这是为很多安全专家和反Rookit工具作者所了解的。我们建议更新反rootkit工具KTHREAD检查机制。
6.作者(Developers)
xrayn 和 joe
7.参考资料(References)
http://www.forum.joebox.org/viewtopic.php?id=38
附注:
SSDT
SSDT的全称是System Services Descriptor Table,系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。
通过修改此表的函数地址可以对常用windows函数及API进行hook,从而实现对一些关心的系统动作进行过滤、监控的目的。一些HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。
Hook
Hook,中文译为“挂钩”或“钩子”,它是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
它实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
网友评论