在windbg,int3中断下输入:
kd> u nt!ZwWriteFile
windbug打印出一下ZwWriteFile反汇编信息
80500300 b812010000 mov eax,112h
80500305 8d542404 lea edx,[esp+4]
80500309 9c pushfd
8050030a 6a08 push 8
8050030c e870e10300 call nt! KeReleaseInStackQueuedSpinLockFromDpcLevel+0x95d (8053e481)
80500311 c22400 ret 24h
80500314 b813010000 mov eax,113h
80500319 8d542404 lea edx,[esp+4]
其中这个pushfd是压入EFLAGS的全部信息。PUSHF(压入标志)与 PUSHFD(压入标志双字)助记符引用相同的操作码。当操作数属性为 16 时,使用 PUSHF 指令,而当操作数属性为 32 时,使用 PUSHFD 指令。某些汇编器可能在使用 PUSHF 时将操作数大小强制为 16,而在使用 PUSHFD 时将操作数大小强制为 32。其它汇编器可能会将这些助记符看作同义词 (PUSHF/PUSHFD),并使用操作数大小属性的当前设置来确定要压入堆栈的值的大小,而不管使用哪一个助记符。
可见80500300 地址是这个函数的入口地址,用dd 80500300 命令查看一下这个内存地址的值:
kd> dd 80500300
80500300 000112b8 24548d00 086a9c04 03e170e8
80500310 0024c200 000113b8 24548d00 086a9c04
80500320 03e15ce8 0024c200 000114b8 24548d00
80500330 086a9c04 03e148e8 0018c200 000115b8
而查看80500300+1内存地址的值
kd> dd 80500300+1
80500301 00000112 0424548d e8086a9c 0003e170
80500311 b80024c2 00000113 0424548d e8086a9c
80500321 0003e15c b80024c2 00000114 0424548d
可见80500301+1的值就是00000112 =》是我们所照的ZwWriteFile的索引号
所以我们使用ZwWriteFile 函数名,即函数入口指针 + 1,即为保存索引号的地址。之后用*取值就得到了索引号。
当我们HOOK SSDT 时,要做的很重要的事情就是要获得NtXXX函数在SSDT中的索引号,以方便替换和调用。
取得索引号会使用宏:
#define HOOK_INDEX(function2hook) *(PULONG)((PUCHAR)function2hook + 1)