SSDT表
系统服务描述符表
这里以Windows XP SP3为例
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 f8b7ba80 f82ffb60 820808f8 806e2f40
80554000 00000000 00000000 00000000 00000000
80554010 28728ec0 01db120e 00000000 00000000
第一个参数指向的是内核函数存储的首地址
kd> dd 80502b8c
ReadVirtual: 80502b8c not properly sign extended
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
第三个参数11c(284)代表的是SSDT表有多少个内核函数
第四个参数指向的是一个地址,这个地址表示的内核函数相对应的参数个数
kd> dd 80503000
ReadVirtual: 80503000 not properly sign extended
80503000 2c2c2018 44402c40 1818080c 0c040408
80503010 08081810 0808040c 080c0404 2004040c
80503020 140c1008 0c102c0c 10201c0c 20141038
80503030 141c2424 34102010 080c0814 04040404
80503040 0428080c 1808181c 1808180c 040c080c
80503050 100c0010 10080828 0c08041c 00081004
80503060 0c080408 10040828 0c0c0404 28240428
80503070 0c0c0c30 0c0c0c18 0c10300c 0c0c0c10
比如0x2c = 44,44/4 = 11个参数
分析
我们来看一个函数OpenProcess是具体怎么调用的
tips:最好是什么编译环境,就在什么环境分析,xp上编的在xp上分析,win10上编的在win10上分析
可以看见,OpenProcess也是调用了kernel32.dll
kernel32.dll里面看见了syscall的调用,调用号是0x7A
这时候找到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 f8b67a80 f82ffb60 81be2928 806e2f40
80554000 00000000 00000000 00000000 00000000
80554010 08909a40 01db1211 00000000 00000000
kd> dd 80502b8c+7a*4
ReadVirtual: 80502d74 not properly sign extended
80502d74 805c2296 805e49fc 805e4660 805a0722
80502d84 8060c254 805ba77a 805c2522 805e4a1a
80502d94 805e47d0 8060e1b0 8063cc78 805c0346
80502da4 805eedce 805eaa16 805eac02 805aea08
80502db4 806062dc 8056d0ce 8060db50 8060db50
80502dc4 8053d02e 80607e68 80608ac8 80570074
80502dd4 805b4de0 805703ca 806063a4 8056d222
80502de4 8060d2dc 80570c46 805ccee0 8059b6fc
在这里0x805c2296就是我们要找的函数调用表的首地址,进去看个伪代码
kd> u 805c2296 L50
805c2296 68c4000000 push 0C4h
805c229b 68a8aa4d80 push offset nt!ObWatchHandles+0x25c (804daaa8)
805c22a0 e86b6cf7ff call nt!_SEH_prolog (80538f10)
805c22a5 33f6 xor esi,esi
805c22a7 8975d4 mov dword ptr [ebp-2Ch],esi
805c22aa 33c0 xor eax,eax
805c22ac 8d7dd8 lea edi,[ebp-28h]
805c22af ab stos dword ptr es:[edi]
805c22b0 64a124010000 mov eax,dword ptr fs:[00000124h]
805c22b6 8a8040010000 mov al,byte ptr [eax+140h]
805c22bc 8845cc mov byte ptr [ebp-34h],al
805c22bf 84c0 test al,al
805c22c1 0f848f000000 je nt!NtOpenProcess+0xc0 (805c2356)
805c22c7 8975fc mov dword ptr [ebp-4],esi
805c22ca a1d4995580 mov eax,dword ptr [nt!MmUserProbeAddress (805599d4)]
805c22cf 8b4d08 mov ecx,dword ptr [ebp+8]
805c22d2 3bc8 cmp ecx,eax
805c22d4 7202 jb nt!NtOpenProcess+0x42 (805c22d8)
805c22d6 8930 mov dword ptr [eax],esi
805c22d8 8b01 mov eax,dword ptr [ecx]
805c22da 8901 mov dword ptr [ecx],eax
805c22dc 8b5d10 mov ebx,dword ptr [ebp+10h]
805c22df f6c303 test bl,3
805c22e2 7405 je nt!NtOpenProcess+0x53 (805c22e9)
805c22e4 e8d5970400 call nt!ExRaiseDatatypeMisalignment (8060babe)
805c22e9 a1d4995580 mov eax,dword ptr [nt!MmUserProbeAddress (805599d4)]
805c22ee 3bd8 cmp ebx,eax
805c22f0 7207 jb nt!NtOpenProcess+0x63 (805c22f9)
805c22f2 8930 mov dword ptr [eax],esi
805c22f4 a1d4995580 mov eax,dword ptr [nt!MmUserProbeAddress (805599d4)]
805c22f9 397308 cmp dword ptr [ebx+8],esi
805c22fc 0f9545e6 setne byte ptr [ebp-1Ah]
805c2300 8b4b0c mov ecx,dword ptr [ebx+0Ch]
805c2303 894dc8 mov dword ptr [ebp-38h],ecx
805c2306 8b4d14 mov ecx,dword ptr [ebp+14h]