《电子技术应用》
您所在的位置:首页 > 通信与网络 > 业界动态 > 网络安全编程:SSDT(系统服务描述表)

网络安全编程:SSDT(系统服务描述表)

2021-07-31
来源:计算机与网络安全
关键词: SSDT 病毒 本地API

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

  使用WinDbg连接到虚拟机上,然后在命令提示符处输入dd KeServiceDescriptorTable命令,会得到一些十六进制的输出。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定义成一个结构体,具体如下:

  typedef struct _SERVICE_DESCRIPTOR_TABLE

  {

  PULONG ServiceTableBase;

  PULONG Reseave;

  ULONG NumberOfServices;

  PUCHAR ParamTableBase;

  }SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

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

  extern PSERVICE_DESCRIPTOR_TABLE 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命令,输出如下:

  kd> u 8059a948

  nt!NtAcceptConnectPort:

  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命令,输出如下:

  kd> u 805e7db6

  nt!NtAccessCheck:

  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,输出如下:

  kd> u 805c2798

  nt!NtQueryPortInformationProcess:

  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()函数的地址。




电子技术图片.png

本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。