WinDbg打印SSDT的参数个数脚本
一、背景
最近开发驱动,需要用到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个参数。