具体判断句柄是不是一个打开端口的方法请参考OpPorts的源代码,在http://rookit.host.sk上可以找到。我们现在来隐藏指定端口。我们已经比较过了InputBufferLength和IoControlCode,现在来比较RemoteAddressLength,对打开端口来说它总是3或4。最后要做的是比较OutputBufferBuffer里的ReceiveTsdus,用网络上的端口和要隐藏的端口列表比较。区别TCP和UDP的做法是句柄的名字不一样。在删除了OutputBuffer、修改IoStatusBlock并返回STATUS_INVALID_ADDRESS后我们就已经隐藏了这个端口了。
=====[ 11. 结束语 ]===============================================
具体细节请参考Hacker defender rootkit version 1.0.0的源代码,在http://rootkit.host.sk和http://www.rootkit.com都可以找到。
在将来我还会加入更多有关的技术。这篇文档的更新版本会改进现有的方法和并加入新的思想。
特别感谢Ratter提供了很多完成这篇文档和Hacker defender代码所需要的技术。
===================================[ End ]==============================
后记:
其实只要我们对Windows的内核有一定程度的了解我们都知道单纯靠挂钩函数是不能真正做到隐藏的,这样做只不过是欺骗操作系统的使用者,却欺骗不了操作系统自己。线程要想被运行就必须获得时间片,将自己加入调度链表中,从而暴露自己。内核维护一组被称为调度程序数据库的数据结构来做出线程调度的决策。其中最重要的结构是调度程序就绪队列(KiDispatckerReadyListHead)。它里面有64个DWORD,分别对应于32个线程优先级的队列,队列包含处于就绪状态的线程,正在等待调度执行。还有两个队列KiWaitInListHead和KiWaitOutListHead保存着处于等待状态的线程。可以很简单的枚举这3个链表中的所有元素从而列出系统中的所有线程。因此要想彻底从Windows系统里“消失”就要从Windows的内核下手(Windows的内核只负责线程调度,其它功能由执行程序组件完成)。这个功能还有待完成。