WinDbg打印SSDT的参数个数脚本

发布时间 2023-07-21 16:01:41作者: 禁锢在时空之中的灵魂

 

一、背景

  最近开发驱动,需要用到SSDT相关函数的参数以选用合适参数个数的函数,此以在之前《Windows驱动开发学习记录-Windbg打印SSDT脚本》的基础上进行改进来显示相关信息。

 

二、SSDT参数表分析

  Windbg分析数据如下:

4: kd> dqs nt!KeServiceDescriptorTable
fffff802`7b0018c0  fffff802`7a2c81f0 nt!KiServiceTable
fffff802`7b0018c8  00000000`00000000
fffff802`7b0018d0  00000000`000001d7
fffff802`7b0018d8  fffff802`7a2c8950 nt!KiArgumentTable
fffff802`7b0018e0  00000000`00000000
fffff802`7b0018e8  00000000`00000000
fffff802`7b0018f0  00000000`00000000
fffff802`7b0018f8  00000000`00000000
fffff802`7b001900  fffff802`7ac112c0 nt!KiBreakpointTrapShadow
fffff802`7b001908  fffff802`7ac11340 nt!KiOverflowTrapShadow
fffff802`7b001910  fffff802`7ac11d40 nt!KiRaiseSecurityCheckFailureShadow
fffff802`7b001918  fffff802`7ac11dc0 nt!KiRaiseAssertionShadow
fffff802`7b001920  fffff802`7ac11e40 nt!KiDebugServiceTrapShadow
fffff802`7b001928  fffff802`7ac13180 nt!KiSystemCall64Shadow
fffff802`7b001930  fffff802`7ac12e40 nt!KiSystemCall32Shadow
fffff802`7b001938  00000000`00000000

  可以看到 nt!KiArgumentTable在 nt!KiServiceTable + 0x18的地方,也即nt!KeServiceDescriptorTable + 0x18的地方。而这个地方是一个字节数组,详细见下:

4: kd> db nt!KiArgumentTable
fffff802`7a2c8950  10 00 08 00 00 00 14 18-14 04 00 00 00 00 00 00  ................
fffff802`7a2c8960  04 04 00 08 00 00 04 08-08 04 04 14 00 0c 00 00  ................
fffff802`7a2c8970  00 04 00 08 00 04 00 04-18 1c 00 04 00 00 14 04  ................
fffff802`7a2c8980  00 00 08 08 00 1c 00 00-04 18 04 00 0c 00 00 04  ................
fffff802`7a2c8990  00 08 08 00 00 04 00 00-04 04 0c 00 00 14 10 00  ................
fffff802`7a2c89a0  04 04 00 00 08 1c 04 08-00 30 00 04 00 00 00 04  .........0......
fffff802`7a2c89b0  08 00 0c 1c 1c 30 34 00-00 00 00 00 08 30 00 00  .....04......0..
fffff802`7a2c89c0  00 00 00 00 04 00 0c 14-00 1c 1c 00 08 00 00 00  ................

  其中每个字节代表一个对应函数调用的参数字节的大小,因在x64的环境下,常规的调用四个之内使用寄存器 rcx,rdx,r8,r9,多于四个才用内存栈。因为表中为0的表示参数个数在4个及以下,而其它的表示除去四个字节后的个数的总字节数,这个数除以8就是除去四个寄存器参数后使用内存传递的参数个数,因此以修改之前的脚本后如下:

aS ufLinkS "<u><col fg=\\\"emphfg\\\"><link name=\\\"%p\\\" cmd=\\\"uf 0x%p\\\">";
aS ufLinkE "</link></col></u>";
 
r $t1 = nt!KeServiceDescriptorTable;
r $t2 = poi(@$t1 + 0x10);
r $t9 = poi(@$t1 + 0x18);
r $t1 = poi(@$t1);

 
.printf "\n\nKeServiceDescriptorTable->KiServiceTable:  %p\nKeServiceDescriptorTable->Count: %d\n", @$t1, @$t2;
.printf "\nOrd   Address   fnAddr  	ArgNum	 Symbols\n";
.printf "--------------------------------\n\n";
 
.for (r $t0 = 0; @$t0 != @$t2; r $t0 = @$t0 + 1)
{
    r @$t3 = (poi(@$t1 + @$t0 * 4)) & 0x00000000`FFFFFFFF;
    $$.printf "2. %p\n", @$t3;
       
	r @$t4 = (poi(@$t9 + @$t0))& 0x00000000`000000FF;
	r @$t4 = @$t4 / 4
	.if (@$t4 > 0)
	{
		r @$t4 = @$t4 + 4;
	}
    .if ( @$t3 & 0x80000000 )
       {
               r @$t3 = (@$t3 >> 4) | 0xFFFFFFFF`F0000000;
               r @$t3 = 0 - @$t3;
               r @$t3 = @$t1 - @$t3;
       }
       .else
       {
           r @$t3 = (@$t3 >> 4);
               r @$t3 = (@$t1 + @$t3);
       }
       
    .printf /D "[%3d] ${ufLinkS}%p${ufLinkE}  [%2d]  (%y) \n", @$t0, @$t3, @$t3, @$t3, @$t4, @$t3;
}
 
.printf "\n- end -\n";

三、运行结果

Win10 x64(21H2)

4: kd> $><E:\DriverProject\脚本及配置文件\x64SSDT.txt


KeServiceDescriptorTable->KiServiceTable:  fffff8027a2c81f0
KeServiceDescriptorTable->Count: 471

Ord   Address   fnAddr  	ArgNum	 Symbols
--------------------------------

[  0] fffff8027a539f60  [ 8]  (nt!NtAccessCheck (fffff802`7a539f60)) 
[  1] fffff8027a545450  [ 0]  (nt!NtWorkerFactoryWorkerReady (fffff802`7a545450)) 
[  2] fffff8027a906e20  [ 6]  (nt!NtAcceptConnectPort (fffff802`7a906e20)) 
[  3] fffff8027aad3a00  [ 0]  (nt!NtMapUserPhysicalPagesScatter (fffff802`7aad3a00)) 
[  4] fffff8027a7f7b90  [ 0]  (nt!NtWaitForSingleObject (fffff802`7a7f7b90)) 
[  5] fffff8027a5fabe0  [ 0]  (nt!NtCallbackReturn (fffff802`7a5fabe0)) 
[  6] fffff8027a88c290  [ 9]  (nt!NtReadFile (fffff802`7a88c290)) 
[  7] fffff8027a874ce0  [10]  (nt!NtDeviceIoControlFile (fffff802`7a874ce0)) 
[  8] fffff8027a88b660  [ 9]  (nt!NtWriteFile (fffff802`7a88b660)) 
[  9] fffff8027a8d6f60  [ 5]  (nt!NtRemoveIoCompletion (fffff802`7a8d6f60)) 
[ 10] fffff8027a8d5810  [ 0]  (nt!NtReleaseSemaphore (fffff802`7a8d5810)) 
[ 11] fffff8027a8899e0  [ 0]  (nt!NtReplyWaitReceivePort (fffff802`7a8899e0)) 
[ 12] fffff8027a82e070  [ 0]  (nt!NtReplyPort (fffff802`7a82e070)) 
[ 13] fffff8027a873bc0  [ 0]  (nt!NtSetInformationThread (fffff802`7a873bc0)) 
[ 14] fffff8027a8732b0  [ 0]  (nt!NtSetEvent (fffff802`7a8732b0)) 
[ 15] fffff8027a7f78c0  [ 0]  (nt!NtClose (fffff802`7a7f78c0)) 
[ 16] fffff8027a85f8e0  [ 5]  (nt!NtQueryObject (fffff802`7a85f8e0)) 
[ 17] fffff8027a878140  [ 5]  (nt!NtQueryInformationFile (fffff802`7a878140)) 
[ 18] fffff8027a8e3200  [ 0]  (nt!NtOpenKey (fffff802`7a8e3200)) 
[ 19] fffff8027a7e8e00  [ 6]  (nt!NtEnumerateValueKey (fffff802`7a7e8e00)) 
[ 20] fffff8027a802660  [ 0]  (nt!NtFindAtom (fffff802`7a802660)) 

  可以看到NtAcccessCheck一共有8个参数, NtWorkerFactoryWorkerReady参数在4个以内,NtDeviceIoControlFile一共有10个参数。