inline-hook,中文译作内联挂钩,是恶意程序和rootkit中颇为流行的一门技术。这门技术通过改写目标函数的头部为jmp指令而完成挂钩,可谓是最邪恶的挂钩技术。
其实,单从技术本身来说,这个东西并不复杂。在32位系统中,一个inline的jmp需要5个字节(机器码0xe9的尺寸和一个DWORD的尺寸),将这5个字节覆盖原有的函数头部,并跳转到自己的函数头就可以了。对于这种情况,一个简易的opcode长度计算函数就可以胜任。当然,对于较为完善的考虑,应该在备份原始代码时进行重定位,参考detours是一个比较可靠的做法。
当然,李马在这里聊inline-hook的目的并不是为了讨论如何设计rootkit,而是如何利用这一技术为我们自己服务。下面举出两个例子,示范一下在ring3使用inline-hook进行安全防护。具体代码就不列了,因为原始代码中丝丝缕缕的耦合太多,牵扯的也太多。
- 保护进程自身,对抗CreateRemoteThread的DLL注入。一般来说,ring3下的DLL注入的标准做法是使用CreateRemoteThread控制目标进程调用LoadLibrary加载DLL,那么我们的程序可以按照以下步骤进行自我保护:
1) 在自身初始化完毕后,挂钩自身的LoadLibraryExW,并在主线程中获取当前线程ID。
2) 在挂钩函数中判断当前线程ID是否和主线程ID相等,如不相等则可能是来自外部的DLL注入,进行拒绝或通知用户处理。
3) 对于自身所需要的LoadLibrary行为,可以在主线程中进行,或调用原始的LoadLibraryExW。
补充一句,在第 2) 步中,应对LOAD_LIBRARY_AS_DATAFILE的加载和msctf.dll放行(放行msctf.dll的原因待考,不放行的话会无响应)。
- 防护IE的漏洞,使恶意程序在通过IE漏洞执行时进行阻挡或询问用户。这个功能其实很简单,只需要写一个DLL,使浏览器在启动的时候可以自动加载它就可以了(BHO是一个不错的选择)。挂钩的函数是CreateProcessA和CreateProcessW(Maxthon2的安全插件则直接挂钩了CreateProcessInternalW),也就是July中所带的插件RunBlocker。