SSDT知识点

0x00 Hook技术

hook技术分为两块:

  • Ring3层的Hook,俗称应用层hook技术
  • Ring0层的Hook,俗称内核层Hook技术

Ring3层的hook又分为两种类型

  • Windows消息的hook
  • WindowsAPI的hook

如下图所示:

hook1
hook2
hook1

关于Windows消息的Hook,相信很多朋友都有接触过的,因为一个SetWindowsHookEx即可以完成消息 Hook,在这里简要介绍一下消息 Hook,消息 Hook 是通过SetWindowsHookEx可以实现将自己的钩子插入到钩子链的最前端,而对于发送给被 Hook 的窗口(也有可能是所有的窗口,即全局 Hook)的消息都会被我们的钩子处理函数所捕获到,也就是我们可以优先于窗体先捕获到这些消息,Windows 消息 Hook 可以实现为进程内消息 Hook 和全局消息 Hook,对于进程内消息 Hook,则可以简单的将 Hook 处理函数直接写在这个进程内,即是自己 Hook 自己,而对于用途更为广泛的全局消息 Hook,则需要将 Hook 处理函数写在一个 DLL 中,这样才可以让你的处理函数被所有的进程所加载(进程自动加载包含 Hook 消息处理函数的 DLL)。

对于 Windows 消息 Hook 呢,可以有个简单的邪恶应用,就是记录键盘按键消息,从而达到监视用户输入的键值信息的目的,这样,对于一些简单的用户通过键盘输入的密码就可以被 Hook 获取到,因为没当用户按下一个键时,Windows 都会产生一个按键消息(当然有按下,弹起等消息的区分),然后我们可以 Hook 到这个按键消息,这样就可以在 Hook 的消息处理函数中获取到用户按下的是什么键了。

不过消息的hook不是本文的重点。

本文要讲的SSDT hook呢其实是属于内核Hook,常见于病毒以及杀软中。

下图展示了内核hook的几个基本类型。

Kernel hook

0x01 SSDT简介

SSDT全称System Service Descriptor Table(系统描述符表),这个表用于将Ring3的Win32API和内核的API联系起来。

SSDT并不仅仅只包含一个庞大的地址索引表,它还包含一些有用的信息,如地址索引的基地址,服务函数的个数等。通过修改此表可以达到对一些关心的系统动作进行过滤以及监控的目的。

在NT4.0的windows操作系统中,默认存在两个系统服务描述符表,这两个描述符表对应了两类不同的系统服务,这两个表为:KeServiceDescriptorTable(SSDT)和KeServiceDescriptorTable(SSDT Shadow)。其中SSDT负责处理来自Ring3层的Kernel32.dll的系统调用。而SSDT Shadow则主要处理来自User32.dll和GDI32.dll的系统调用。同时SSDT在ntoskrnl.exe中是导出的,而SSDT Shadow如其名是未被Windows所导出的,而关于SSDT的全部内容都是通KeServiceDescriptorTable来完成的。

以下截图说明,KeServiceDescriptorTable是在ntoskrnl.exe中被导出的:

Export1

随后我们看看看看Windows操作系统的源码中如何定义KeServiceDescriptorTable的,通过观察WRK可知,

KeServiceDescriptorTable in WRK

这么看还是有点蛋疼啊。改写以下变量的名称吧。

    typedef struct _KSYSTEM_SERVICE_TABLE{
        PULONG ServiceTableBase;            //SSDT的基地址指针
        PULONG ServiceCounterTableBase; //SSDT中每个服务被调用次数表的基地址指针
        ULONG NumberOfService;              //服务函数个数,NumberOfService*4就是整个地址表的大小
        ULONG ParamTableBase;               //SSPT的基地址
    }KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE;
    typedef struct _KSERVICE_TABLE_DESCRIPTOR{
        KSYSTEM_SERVICE_TABLE ntoskrnl;     //ntoskrnl.exe的服务函数
        KSYSTEM_SERVICE_TABLE win32k;       //win32k.sys的服务函数(GDI32/User32)
        KSYSTEM_SERVICE_TABLE notUsed1;
        KSYSTEM_SERVICE_TABLE notUsed2;
    }KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR;
    //导出由ntoskrnl.exe所导出的SSDT
    extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

从上述介绍可知,KeServiceDescriptorTable可以看做是一个数组,是4个KSYSTEM_SERVICE_TABLE结构形成的数组,而每个KSYSTEM_SERVICE_TABLE对应一个PE文件导出的服务描述符表,根据这些服务描述符表我们可以获得更加详细的服务信息。在应用层ntdll.dll中的API在这个系统服务描述表中都存在一个与之对应的服务,当我们的应用程序调用ntdll.dll里的API时最终可以调用对应的系统服务函数,通知给内核一个索引,内核通过该索引在SSDT中查找对应的服务,内核调用服务完成应用的API调用请求。

应用层调用Win32API流程

有了以上的SSDT基础后,我们再来看看在应用层调用Win32API(主要指ntdll.dll中的API)的流程,我们主要针对ntdll.dll中的NtQuerySystemInformation这个API的调用流程来进行阐述。

这里存在四个类似的API。

4APIs

再给出这些API的调用流程。

calling way

这里我们可以看到ntdll.dll中的nt和zw都会进入内核层去调用ntoskrnl的zw函数,而zw最终会调用nt函数,这个函数作为内核API最终去请求系统服务的执行。
用exescope工具可以打开ntdll.dll,看到NtQuerySystemInformation以及ZwQuerySystemInformation。

ntdll1

ntdll2

而实质上zw和nt都是同一函数,指向同一区域,入口地址相同。

因此Ntdll.dll中的API都是对内核API的封装,当Kernel32.dll中的API通过Ntdll.dll去调用系统API时,会进行参数检查,并调用中断(int 2Eh或SysEnter),从而从Ring3进入Ring0,并将所要调用的服务号,即SSDT数组的索引值,存放进寄存器EAX中,并且将参数地址放到指定的寄存器EDX中,再复制参数到内核地址空间,根据存放在EAX中的索引值来在SSDT数组中调用指定的服务。

经过上面步骤我们来到Ring0层。使用exescope看看ntoskrnl.exe中的ZwQuerySystemInformation以及NtQuerySystemInformation。

ntoskrnl1
ntoskrnl2

再反汇编ntoskrnl这个文件可以看到Zw函数中调用KiSystemService系统服务分发函数时往EAX中存放了索引号ADh。如图:

ZwQSystemInfor

随后根据该索引值检索SSDT项,最后根据该SSDT项中所存放的系统服务地址来调用这个系统服务。在这里就是调用KeServiceDescriptorTable[ADh]处保存的地址对应的系统服务。那就是Ring0下的NtQuerySystemInformation。

0x02 详解SSDT

这节内我们用WinDbg来调试XP系统,借此说明SSDT是个什么鬼。
据我们上文的结构定义可知,KeServiceDescriptorTable是一个指向4个KSYSTEM_SERVICE_TABLE结构首地址的指针,以下图为例吧。

dd KeServiceDescriptorTable

这里的0x80563520这一行就是ntoskrnl对应的服务描述符表结构KSYSTEM_SERVICE_TABLE。那么第一个32位的0x804e58a0则是对应ntoskrnl对应的KSYSTEM_SERVICE_TABLE中的SSDT Base,即服务描述符表的首地址。通过对该首地址的dump,我们可以看到许多以128位为一组排列的服务描述符,每个描述符中的第一个32位(0x80591bfb)对应着系统服务的入口地址。通过对该入口地址的反汇编,可以看到这是SSDT第一个系统服务NtAcceptConnectPort函数。如图:

NtAcceptConnectPort

那么知道了SSDT首地址,同时知道了索引,那么我们就可以通过索引来找到对应的系统服务入口地址了。通过计算“SSDT中系统服务地址所在的地址 = SSDT首地址 + 4 * 索引值”,可以推算出NtQuerySystemInformation的起始地址位0x80586ff1,对该地址进行反汇编,可得下图:

NtQuerySystemInformation

由此可知,SSDT就是个保存Windows系统服务地址的数组。

0x03 SSDT hook原理

从上面的分析中我们可以看到SSDT数组中保存了系统服务的地址,如Ring0下的NtQuerySystemInformation系统服务地址,就保存在KeServiceDescriptorTable[ADh]中,既然hook就是取出这个地址后替换上我们的hook函数,在hook函数中执行原函数即可。

参考文献:

http://www.cnblogs.com/boyxiao/archive/2011/09/03/2164574.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,669评论 0 27
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 1. 结构体和共同体的区别。 定义: 结构体struct:把不同类型的数据组合成一个整体,自定义类型。共同体uni...
    breakfy阅读 2,072评论 0 21
  • 我不是 注定和这黑夜 分不出彼此 如果蓝色就是忧郁 在海边我就要死死把你抱住
    萨先生阅读 244评论 0 0