查看64位SSDT中服务函数地址
以Windows 7 x64为例。
- 原理:在ntdll中,反汇编Nt*函数,在第二行可以看到对应索引,根据索引在nt模块中,根据公式计算服务函数地址
- 方法:
- 使用windbg + 虚拟机,加载ntdll.dll符号,在ntdll.dll中反汇编对应Zw*函数寻找索引(Nt*函数也可以,因为它俩地址是一样的)
- 定位SSDT地址,找到基址,根据pFuncAddr = ServiceBase + ServiceBase[index] >> 4
计算函数地址。
1、寻找Nt*函数索引
- 查看是否已经加载ntdll.dll的符号,查看已加载模块命令:
lm l
- 如果未加载,下载符号(你懂的),输入命令:
.reload /f ntdll.dll
- 如果已加载,查看对应Zw*函数反汇编代码,以
ZwCreateFile
为例,第二行中52h
即索引号。
- 如果出现反汇编错误:Memory access error,重新加载下符号:
.reload
,或切换至一个用户层进程
kd> u ntdll!ZwCreateFile
ntdll!NtCreateFile:
00000001`8009cb00 ?? ???
^ Memory access error in 'u ntdll!ZwCreateFile'
#查看当前进程
kd> .process
Implicit process is now fffffa80`18db8990
#查看当前explorer进程信息
kd> !process 0 0 explorer.exe
PROCESS fffffa801a65db30
SessionId: 1 Cid: 04cc Peb: 7fffffd8000 ParentCid: 04a0
DirBase: 11c1d000 ObjectTable: fffff8a001cc7c00 HandleCount: 628.
Image: explorer.exe
#切换进程
kd> .process /p /i fffffa801a65db30
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
fffff800`040c9cf0 cc int 3
#查看反汇编代码
kd> u ntdll!ZwCreateFile
ntdll!ZwCreateFile:
00000000`770b1860 4c8bd1 mov r10,rcx
00000000`770b1863 b852000000 mov eax,52h
00000000`770b1868 0f05 syscall
00000000`770b186a c3 ret
00000000`770b186b 0f1f440000 nop dword ptr [rax+rax]
ntdll!NtQueryEvent:
00000000`770b1870 4c8bd1 mov r10,rcx
00000000`770b1873 b853000000 mov eax,53h
00000000`770b1878 0f05 syscall
2、定位SSDT表
kd> x nt!KeService*Table*
fffff800`0430b940 nt!KeServiceDescriptorTable = <no type information>
fffff800`0430b980 nt!KeServiceDescriptorTableShadow = <no type information>
kd> dq fffff800`0430b940
fffff800`0430b940 fffff800`040d2b00 00000000`00000000
fffff800`0430b950 00000000`00000191 fffff800`040d378c
fffff800`0430b960 00000000`00000000 00000000`00000000
fffff800`0430b970 00000000`00000000 00000000`00000000
fffff800`0430b980 fffff800`040d2b00 00000000`00000000
fffff800`0430b990 00000000`00000191 fffff800`040d378c
fffff800`0430b9a0 fffff960`001c1f00 00000000`00000000
fffff800`0430b9b0 00000000`0000033b fffff960`001c3c1c
3、查看是否正确
kd> dd fffff800`040d2b00
fffff800`040d2b00 0415a800 02f79c00 fff6f000 02eb4805
fffff800`040d2b10 031f8406 03160105 02be1601 02b7dc00
fffff800`040d2b20 03178000 03e57200 02ca4a00 02eaa140
fffff800`040d2b30 02f8c400 02e2a281 02df8401 02db6800
fffff800`040d2b40 02e1c402 02f45800 02afd1c0 02d10601
fffff800`040d2b50 02d22502 02f8dc02 0313c801 03262301
fffff800`040d2b60 045d8905 02eff700 02b5d203 ffec2b00
fffff800`040d2b70 0443ed00 02f75040 02c72f01 03171f00
#查看索引号为0的服务函数
kd> u fffff800`040d2b00 + 0415a80
nt!NtMapUserPhysicalPagesScatter:
fffff800`044e8580 48895c2408 mov qword ptr [rsp+8],rbx
fffff800`044e8585 4c89442418 mov qword ptr [rsp+18h],r8
fffff800`044e858a 55 push rbp
fffff800`044e858b 56 push rsi
fffff800`044e858c 57 push rdi
fffff800`044e858d 4154 push r12
fffff800`044e858f 4155 push r13
fffff800`044e8591 4156 push r14
#查看NtMapUserPhysicalPagesScatter在ntdll中的索引,是0证明正确
kd> u ntdll!NtMapUserPhysicalPagesScatter
ntdll!ZwMapUserPhysicalPagesScatter:
00000000`770b1340 4c8bd1 mov r10,rcx
00000000`770b1343 b800000000 mov eax,0
00000000`770b1348 0f05 syscall
00000000`770b134a c3 ret
00000000`770b134b 0f1f440000 nop dword ptr [rax+rax]
可以看到,NtMapUserPhysicalPagesScatter
服务函数索引为0,SSDT表的ServiceBase为fffff800 040d2b00
,指向的第一个整数为0415a800
,根据计算公式 ,服务函数地址= ServiceBase + (ServiceBase [索引] >> 4)
,查看反汇编代码,确实是NtMapUserPhysicalPagesScatter
,证明正确。
由于在64位系统中,SSDT表不再直接存储服务函数地址,而是存储偏移地址>>4,所以
dps
和dqs
不能直接显示函数名字,只能看反汇编代码,确定函数名。
4、查看NtCreateFile地址
由于NtCreateFile索引是52h,所以显示53h个元素,最后一个即偏移地址。
kd> dd fffff800`040d2b00 L1
fffff800`040d2b00 0415a800
kd> dd fffff800`040d2b00 L53
fffff800`040d2b00 0415a800 02f79c00 fff6f000 02eb4805
fffff800`040d2b10 031f8406 03160105 02be1601 02b7dc00
fffff800`040d2b20 03178000 03e57200 02ca4a00 02eaa140
fffff800`040d2b30 02f8c400 02e2a281 02df8401 02db6800
fffff800`040d2b40 02e1c402 02f45800 02afd1c0 02d10601
fffff800`040d2b50 02d22502 02f8dc02 0313c801 03262301
fffff800`040d2b60 045d8905 02eff700 02b5d203 ffec2b00
fffff800`040d2b70 0443ed00 02f75040 02c72f01 03171f00
fffff800`040d2b80 02db6a02 02d50a40 02ef3fc1 02d40700
fffff800`040d2b90 02e01901 031da806 02e5b407 031b6540
fffff800`040d2ba0 03178201 02bb2140 041a7600 026ab385
fffff800`040d2bb0 02d4b001 02dc9ec0 02b29000 02ba2f02
fffff800`040d2bc0 02eaae02 02f7ae00 02eb1b07 030d1dc0
fffff800`040d2bd0 031de200 041a3001 02db5ec6 02a7c781
fffff800`040d2be0 02d79ac0 02da9903 02dcbd00 02ebf880
fffff800`040d2bf0 02a7de41 02e33500 02b6ef02 02a6f482
fffff800`040d2c00 0000e400 03b1da00 02e69a01 ffce4600
fffff800`040d2c10 02587dc0 02c6ba01 03188001 02dc7683
fffff800`040d2c20 029fab00 02e1f200 0477bf05 03e58504
fffff800`040d2c30 041adb00 031c6b01 0320e6c1 02f2b500
fffff800`040d2c40 02d72900 046b0c02 030acdc7
kd> u fffff800`040d2b00 + 030acdc
nt!NtCreateFile:
fffff800`043dd7dc 4c8bdc mov r11,rsp
fffff800`043dd7df 4881ec88000000 sub rsp,88h
fffff800`043dd7e6 33c0 xor eax,eax
fffff800`043dd7e8 498943f0 mov qword ptr [r11-10h],rax
fffff800`043dd7ec c744247020000000 mov dword ptr [rsp+70h],20h
fffff800`043dd7f4 89442468 mov dword ptr [rsp+68h],eax
fffff800`043dd7f8 498943d8 mov qword ptr [r11-28h],rax
fffff800`043dd7fc 89442458 mov dword ptr [rsp+58h],eax