Windows系统调用中的系统服务表描述符(SSDT)
一、使用PELord函数从ntoskrnl.exe文件中查看SSDT导出函数
如图,可以看出KeServiceDescriptorTable导出函数。
通过该函数可以查找SSDT表的位置。
二、通过Windbg来内存中查看SSDT表
使用Windbg,可以使用 kd> dd nt!KeServiceDescriptorTable 指令来查看SSDT表。
但该指令存在缺点,可以看到第二张表为0,说明如果使用KeServiceDescriptorTable这个公开的导出函数,我们无法看到win32k.sys这张表结构
kd> dd nt!KeServiceDescriptorTable
83f759c0 83e89d9c 00000000 00000191 83e8a3e4
83f759d0 00000000 00000000 00000000 00000000
83f759e0 83ee86af 00000000 0327aa43 000000bb
83f759f0 00000011 00000100 5385d2ba d717548f
为了解决上面这个问题,我们只能使用另外一个指令,该指令对应的是一个未公开导出的函数。
如下,可以看到其第二行,win32k.sys系统服务表已经可见。
kd> dd KeServiceDescriptorTableShadow
83f75a00 83e89d9c 00000000 00000191 83e8a3e4
83f75a10 83b66000 00000000 00000339 83b6702c
83f75a20 00000000 00000000 83f75a24 00000340
83f75a30 00000340 855e8440 00000007 00000000
三、验证ReadMemory真正的内核实现部分
其依次分别为 ServiceTable 83e89d9c,Count 00000000,ServiceLimit 00000191,ServiceTable 83e8a3e4
使用Windbg来查看其115h序号的函数地址 115h*4 + 83e89d9c (ServiceTable)
得到函数地址为 8406c82c
kd> dd 115h*4 + 83e89d9c
83e8a1f0 8406c82c 840feb46 83fb488c 83fb6128
再对此进行反汇编可得
kd > u 8406c82c
nt!NtReadVirtualMemory:
8406c82c 6a18 push 18h
8406c82e 68282ae683 push offset nt!? ? ::FNODOBFM::`string'+0x3ea8 (83e62a28)
8406c833 e870e3e1ff call nt!_SEH_prolog4(83e8aba8)
8406c838 648b3d24010000 mov edi, dword ptr fs : [124h]
8406c83f 8a873a010000 mov al, byte ptr[edi + 13Ah]
8406c845 8845e4 mov byte ptr[ebp - 1Ch], al
8406c848 8b7514 mov esi, dword ptr[ebp + 14h]
8406c84b 84c0 test al, al
之后,我们查看该nt!NtReadVirtualMemory函数的参数个数
kd > db 83e8a3e4 + 115
83e8a4f9 14 08 04 04 14 04 10 08 - 0c 04 14 18 08 08 08 0c
83e8a509 0c 08 10 14 08 08 0c 08 - 0c 0c 04 08 08 08 08 08
83e8a519 08 0c 0c 24 00 08 08 08 - 0c 04 08 04 08 10 08 04
四、通过修改SSDT表增添系统服务函数
1 #include "pch.h" 2 #include <iostream> 3 #include <algorithm> 4 #include <Windows.h> 5 void ReadMemory(HANDLE hProcess, PVOID pAddr, PVOID pBuffer, DWORD dwSize, DWORD *dwSizeRet) 6 { 7 8 _asm 9 { 10 lea eax, [ebp + 0x14] 11 push eax 12 push[ebp + 0x14] 13 push[ebp + 0x10] 14 push[ebp + 0xc] 15 push[ebp + 8] 16 sub esp, 417 mov eax, 0x192 // 注意:修改的是这里18 mov edx, 0X7FFE0300 //sysenter不能直接调用,我间接call的19 CALL DWORD PTR[EDX] 20 add esp,