Windows 网络编程:系统服务描述表

2019 年 3 月 14 日 计算机与网络安全

一次性进群,长期免费索取教程,没有付费教程。

教程列表见微信公众号底部菜单

微信群回复公众号:微信群QQ群460500587


微信公众号:计算机与网络安全

ID:Computer-network

一、SSDT


本文将介绍内核下的一张非常有用的表。在很多游戏保护系统中,或在一些杀毒软件中,都会对该表进行修改,从而改变系统函数调用流程来起到反外挂、反病毒的作用。同样,病毒也在修改该表,从而修改系统函数调用流程来完成其自身的目的。这张非常关键的表叫做SSDT,即System Service Descriptor Table(系统服务描述表)。这张表的作用是把用户层的Win32 API和内核层的API建立一个关联。在该表中维护非常多的Native API,或称本地API。下面通过WinDbg来查看一下该表。


使用WinDbg连接到虚拟机上,然后在命令提示符处输入ddKeServiceDescriptorTable命令,会得到一些十六进制的输出。KeServiceDescriptorTable是Ntoskrnl.exe导出的一个指针,用来指向SSDT表的。我们查看一下命令的输出结果:


kd> dd KeServiceDescriptorTable

80553fa0 80502b8c 00000000 0000011c 80503000

80553fb0 00000000 00000000 00000000 00000000

80553fc0 00000000 00000000 00000000 00000000

80553fd0 00000000 00000000 00000000 00000000

80553fe0 00002710 bf80c0b6 00000000 00000000

80553ff0 fc142a80 80e2d890 80cee0f0 806e2f40

80554000 00000000 00000000 c169a786 00009a34

80554010 3beab1c6 01cc052a 00000000 00000000


在该输出中,第一行就是SSDT表,该表中的80502b8c是一个函数指针数组,该指针数组保存了所有Native API的函数地址,0000011c是数组的大小,80503000里面保存的是一个参数个数数组,与Native API相对应。将SSDT定义成一个结构体,如下:

要想在驱动中获得该表,需要使用Notokrnl.exe导出的KeServiceDescriptorTable,将其定义如下:

有了上面的SSDT表和KeServiceDescriptorTable的定义,就可以编写与SSDT相关的程序了,不过似乎还少点什么。表里面对应的Native API到底是什么?用WinDbg来看一下,输入dd 80502b8c,输出结果如下:


kd> dd 80502b8c

80502b8c 8059a948 805e7db6 805eb5fc 805e7de8

80502b9c 805eb636 805e7e1e 805eb67a 805eb6be

80502bac 8060cdfe 8060db50 805e31b4 805e2e0c

80502bbc 805cbde6 805cbd96 8060d424 805ac5ae

80502bcc 8060ca3c 8059edbe 805a6a00 805cd8c4

80502bdc 80500828 8060db42 8056ccd6 8053600e

80502bec 806060d4 805b2c3a 805ebb36 8061ae56

80502bfc 805f0028 8059b036 8061b0aa 8059a8e8


全都是一些地址值比较接近的函数地址,为什么说是函数地址,因为这是函数指针数组。输入u 8059a948命令,输出如下:

8059a948 689c000000   push 9Ch

8059a94d 6838a14d80   push offset nt!_real+0x128 (804da138)

8059a952 e8b9e5f9ff   call nt!_SEH_prolog (80538f10)

8059a957 64a124010000   mov  eax,dword ptr fs:[00000124h]

8059a95d 8a8040010000   mov  al,byte ptr [eax+140h]

8059a963 884590    mov  byte ptr [ebp-70h],al

8059a966 84c0     test al,al

8059a968 0f84b9010000   je  nt!NtAcceptConnectPort+0x1df (8059ab27)


从输出可以看出,8059a948是NtAcceptConnectPort()函数的地址。再来看一个地址,输入u 805e7db6命令,输出如下:

805e7db6 8bff   mov   edi,edi

805e7db8 55    push  ebp

805e7db9 8bec   mov   ebp,esp

805e7dbb 33c0   xor   eax,eax

805e7dbd 50    push  eax

805e7dbe ff7524   push  dword ptr [ebp+24h]

805e7dc1 ff7520   push  dword ptr [ebp+20h]

805e7dc4 ff751c   push  dword ptr [ebp+1Ch]


这次输出的是NtAccessCheck()函数的反汇编代码。在SSDT表中,第3个参数告诉我们,这个数组的大小是0x11c,也就是数组最后一项的下标是0x11b。再看一下下标为0x11b中保存的地址是多少,输入命令dd 80502b8c+11b *4,80502b8c是数组的起始地址,11b是数组下标,那么乘4的是什么原因呢?数组地址的定位是通过数组首地址+下标×数组元素字节数得出的。一个函数的地址占用4个字节,因此要做乘4的操作。该命令输出如下:


kd> dd 80502b8c + 11b * 4

80502ff8 805c2798 0000011c 2c2c2018 44402c40

80503008 1818080c 0c040408 08081810 0808040c

80503018 080c0404 2004040c 140c1008 0c102c0c

80503028 10201c0c 20141038 141c2424 34102010

80503038 080c0814 04040404 0428080c 1808181c

80503048 1808180c 040c080c 100c0010 10080828

80503058 0c08041c 00081004 0c080408 10040828

80503068 0c0c0404 28240428 0c0c0c30 0c0c0c18


再用u命令来查看805c2798处的反汇编代码,输入命令u 805c2798,输出如下:

805c2798 64a124010000 mov  eax,dword ptr fs:[00000124h]

805c279e 8b4844  mov  ecx,dword ptr [eax+44h]

805c27a1 83b9bc00000000 cmp  dword ptr [ecx+0BCh],0

805c27a8 740d   je   nt!NtQueryPortInformationProcess+0x1f (805c27b7)

805c27aa f6804802000004 test  byte ptr [eax+248h],4

805c27b1 7504   jne  nt!NtQueryPortInformationProcess+0x1f (805c27b7)

805c27b3 33c0   xor  eax,eax

805c27b5 40   inc  eax


数组中最后一项保存的是NtQueryPortInformationProcess()函数的地址。

二、HOOK SSDT


SSDT把用户层的Win32 API与内核层的Native API做了一个关联,而整个Native API都保存在SSDT中的一个函数指针数组中,只要修改函数指针数组中的某一项,就相当于HOOK了某个Native API函数。比如,修改SSDT中函数指针数组中的最后一个函数指针,那么就相当于HOOK了NtQueryPortInformationProcess()函数。


下面HOOK一个我们比较熟悉的函数,即创建进程函数NtCreateProcessEx()。该函数在指针数组的第0x30项(该编号根据系统版本的不同而不同,是系统相关的)。通过编程获取SSDT表,然后找到Native API的函数指针数组,然后修改其中第0x30项的内容为我们的函数地址,为了不影响进程的正常创建,在函数中调用NtCreateProcessEx()函数。代码如下:

在DriverEntry()中,调用了HookCreateProcess()函数,该函数的作用就是将指针数组中NtCreateProcessEx()函数的地址替换为MyNtCreateProcess()函数的地址。而MyNtCreateProcess()函数是用来取代NtCreateProcess()函数的函数,在我们的函数中调用了一条KdPrint()用于输出的代码。整个Hook的过程非常简单,只要找到指针数组的位置,保存原地址后修改为新的地址即可。在代码中出现了两个函数,分别是UN_PROTECT()和RE_PROTECT()。这两个函数的作用是,禁止和开启CPU向标志为只读的内存页进行写入的操作。执行了UN_PROTECT后CPU可以向标志为只读的内存页进行写入操作。当写入完成好后,调用RE_PROTECT()函数恢复到原来的状态。把它放到虚拟机中,打开DebugView然后加载该驱动,加载成功后随便运行一个可执行程序,可以看到在DebugView中显示了在MyNtCreateProcess()中的输出了,如图1所示,说明我们的HOOK成功了。

图1  MyCreateProcess()函数的输出

三、Inline HOOK SSDT


为什么要介绍Inline HOOK SSDT呢?在有些情况下,反病毒软件会保护SSDT不受篡改,其保护方式是检查NativeAPI的函数指针数组中的值是否正确。如果其中某项或某几项被修改,那么反病毒软件会将被修改的项恢复到原来的值,这样HOOK SSDT就不成功了。Inline Hook是修改被HOOK的入口字节为一个跳转,从而跳转入函数中。如果换作是Inline Hook SSDT的话,那么就不会去修改Native API的函数指针数组中的值了,这样可以避免反病毒软件的检测(注:这只是一个简单的说明,现在使用Inline HOOK SSDT同样会被反病毒软件查杀)。


实现Inline Hook SSDT的代码如下:

关于代码的部分就不多介绍了,测试一下,其运行结果如图2所示。

图2  Inline Hook

微信公众号:计算机与网络安全

ID:Computer-network

【推荐书籍】
登录查看更多
0

相关内容

应用程序接口(简称 API),又称为应用编程接口,就是软件系统不同组成部分衔接的约定。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
模型优化基础,Sayak Paul,67页ppt
专知会员服务
75+阅读 · 2020年6月8日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
和积网络综述论文,Sum-product networks: A survey,24页pdf
专知会员服务
23+阅读 · 2020年4月3日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
Keras作者François Chollet推荐的开源图像搜索引擎项目Sis
专知会员服务
29+阅读 · 2019年10月17日
msf实现linux shell反弹
黑白之道
49+阅读 · 2019年8月16日
Windows开源无人机仿真工具:AirSim1.0 入门
无人机
25+阅读 · 2019年6月8日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
一个牛逼的 Python 调试工具
机器学习算法与Python学习
15+阅读 · 2019年4月30日
“黑客”入门学习之“windows系统漏洞详解”
安全优佳
8+阅读 · 2019年4月17日
Python用于NLP :处理文本和PDF文件
Python程序员
4+阅读 · 2019年3月27日
深度学习 | 免费使用Google Colab的GPU云计算平台
沈浩老师
12+阅读 · 2018年2月4日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Caffe 深度学习框架上手教程
黑龙江大学自然语言处理实验室
14+阅读 · 2016年6月12日
Arxiv
24+阅读 · 2020年3月11日
Arxiv
20+阅读 · 2019年11月23日
Arxiv
35+阅读 · 2019年11月7日
Arxiv
4+阅读 · 2019年8月7日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Recurrent Fusion Network for Image Captioning
Arxiv
3+阅读 · 2018年7月31日
Arxiv
7+阅读 · 2018年1月10日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
模型优化基础,Sayak Paul,67页ppt
专知会员服务
75+阅读 · 2020年6月8日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
和积网络综述论文,Sum-product networks: A survey,24页pdf
专知会员服务
23+阅读 · 2020年4月3日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
Keras作者François Chollet推荐的开源图像搜索引擎项目Sis
专知会员服务
29+阅读 · 2019年10月17日
相关资讯
msf实现linux shell反弹
黑白之道
49+阅读 · 2019年8月16日
Windows开源无人机仿真工具:AirSim1.0 入门
无人机
25+阅读 · 2019年6月8日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
一个牛逼的 Python 调试工具
机器学习算法与Python学习
15+阅读 · 2019年4月30日
“黑客”入门学习之“windows系统漏洞详解”
安全优佳
8+阅读 · 2019年4月17日
Python用于NLP :处理文本和PDF文件
Python程序员
4+阅读 · 2019年3月27日
深度学习 | 免费使用Google Colab的GPU云计算平台
沈浩老师
12+阅读 · 2018年2月4日
教你用Python来玩跳一跳
七月在线实验室
6+阅读 · 2018年1月2日
Caffe 深度学习框架上手教程
黑龙江大学自然语言处理实验室
14+阅读 · 2016年6月12日
相关论文
Arxiv
24+阅读 · 2020年3月11日
Arxiv
20+阅读 · 2019年11月23日
Arxiv
35+阅读 · 2019年11月7日
Arxiv
4+阅读 · 2019年8月7日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Recurrent Fusion Network for Image Captioning
Arxiv
3+阅读 · 2018年7月31日
Arxiv
7+阅读 · 2018年1月10日
Arxiv
3+阅读 · 2012年11月20日
Top
微信扫码咨询专知VIP会员