.386
.model flat,stdcall
option casemap:none
include ntstatus.inc
include ntddk.inc
include ntoskrnl.inc
includelib ntoskrnl.lib
.code
GetServiceDescriptorTableShadowAddress proc uses esi edi ebx
;本函数摘自kmdkit。本人加一些注释,及自己的理解。
local dwThreadId:DWORD
xor ebx, ebx ; = NULL. Assume ServiceDescriptorTableShadow will be not found
mov eax, KeServiceDescriptorTable
mov esi, [eax]
; Find KTHREAD.ServiceTable field
; For non-GUI threads this field == KeServiceDescriptorTable
; and it points to ServiceDescriptorTable
; For GUI threads
; ServiceDescriptorTableShadow
invoke KeGetCurrentThread ;得到KTHREAD的结构。
mov edi, 200h-4;1;200h-4 ;为什么是这个数呢?换成1,inc edi呢?
.while edi
.break .if dword ptr [eax][edi] == esi ;经查资料0x0e0 ServiceTable : Ptr32 Void。
dec edi;inc edi;dec edi
.endw
.if edi != 0
; edi = offset to ServiceTable field in KTHREAD structure
mov dwThreadId, 080h ;为什么是这个数呢?
.while dwThreadId < 400h ;为什么是这个数呢?
push eax ; reserve DWORD on stack
invoke PsLookupThreadByThreadId, dwThreadId, esp
pop ecx ; -> ETHREAD/KTHREAD
.if eax == STATUS_SUCCESS
push dword ptr [ecx][edi] ;这就是那个表,ssdt或者shadow.
fastcall ObfDereferenceObject, ecx
pop eax ;这儿就应该是返回值。
.if eax != esi ;如果这是一个GUI线程。就返回结束吧!