2024年4月11日发(作者:)

【原创】SSDT HOOK拦截远线程的创建(上)

/logs/

ml

2009-04-12

分类:内核编程

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明

/logs/

注:本文已发表在2009年第3期《黑客防线》,转载请注明来源。

在ring3的API HOOK中,怎样迫使目标进程调用我们的傀儡DLL是我们非常重视的一个

问题。在多数情况下,我们都喜欢使用CreateRemoteThread在目标进程中创建一个远程线程

来迫使它加载我们的DLL。

因为CreateRemoteThread的使用方法并不复杂,而且与其他方式相比,它可以称得上是一

种相当“优雅”的做法。各种因素的汇集就导致了这种方法的泛滥,致使很多具备主动防御或行为

监控的安全软件都加强了对这个函数的照顾。

最近在自己的毕业设计中也要用到这个功能,阻止一些简单地调用CreateRemoteThread

注入到我们要保护的进程中,就对这个问题稍微学习了下。

根据我们的思维惯性,很显然我们应该HOOK CreateRemoteProcess函数,这在ring3

下非常容易实现,但是如果这样的话我们的保护也太没有强度可言了。正好最近正在学习SSDT

HOOK,就使用这个方法吧,算是在实战中磨炼自己,吼吼~~

第一部分:SSDT HOOK的使用方法

关于什么是SSDT等基本概念我就不再赘述了,网上有很多文章,而且黑防以前的杂志上

也有不少详细介绍,这里我推荐一篇李马的《城里城外看SSDT》,确实不错。我一开始是修改

《Rootkits——Windows内核的安全防护》关于SSDT的示例代码,它给出了一个挂钩

ZwQuerySystemInformation来隐藏进程的示例。

很不幸的是,当我照本宣科地把ZwQuerySystemInformation修改成ZwCreateThread

(第二部分会介绍,这里只要知道CreateRemoteThread是最终调用ZwCreateThread)后,

编译器报错:“error LNK2019: unresolved external symbol

__imp__ZwCreateThread@32 referenced in function _DriverEntry@8”。这个错误令我

诧异了很久,在尝试解决问题的过程中,偶然发现了出现问题的原因,原来ZwCreateThread

函数没有被导出(使用depends看看就知道了)。

与之同时,我们在函数中用到了几个宏,它们的详细定义如下:

#define SYSTEMSERVICE(_Function)

eTableBase[ *(PULONG)((PUCHAR)_Fu

nction+1)]

#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HOOK_SYSCALL(_Function, _Hook, _Orig )

_Orig = (PVOID) InterlockedExchange( (PLONG)

&MappedSystemCallTable

[SYSCALL_INDEX(_Function)], (LONG) _Hook)

#define UNHOOK_SYSCALL(_Function, _Hook,

_Orig) InterlockedExchange((PLONG)

&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG)

_Hook)

而SYSTEMSERVICE宏是采用由导出的Zw*函数地址,并返回对应的Nt*

函数在SSDT中的地址,SYSCALL_INDEX采用Zw*函数地址并返回它在SSDT中相应的索

引号。

由于ZwCreateThread没有被导出,所以这时我们就无法直接使用上述的

宏,只能另想他法。

这时候最常规的方法就是从ntdll中动态获取地址,不过我不想那么麻烦。昨天在群里问了

下,iceboy大牛给出了一种猥琐的方法,因为ZwCreateThread在SSDT中的前后两个函数

都被导出了,分别是ZwCreateSymbolicLinkObject和ZwCreateTimer。

这时候我们就可以分别获取这两个函数的索引,判断它们的索引之差是否为2,如果是,则

它们中间的函数就是ZwCreateThread,代码如下所示:

a = SYSCALL_INDEX(ZwCreateSymbolicLinkObject);

b = SYSCALL_INDEX(ZwCreateTimer);

c = b - a;