在研究一段HOOK SSDT的代码中看到有这样一段宏:
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
根据代码注释得知次宏是用来获得SSDT基地址。但是对于这个宏的为何如此定义,一直无法理解。希望有内核驱动开发经验的朋友指点一下。
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
根据代码注释得知次宏是用来获得SSDT基地址。但是对于这个宏的为何如此定义,一直无法理解。希望有内核驱动开发经验的朋友指点一下。
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] 如:
SYSTEMSERVICE(test)
==>
KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)test+1)]
是一个系统定义的全局的结构体变量,ServiceTableBase指向SSDT基地址。
ntoskrnl!ZwOpenKey
0008:80400E2A B867000000 MOV EAX,00000067
| |_ServiceID
|_机器码(其中第二字节即ZwOpenKey线性地址加一处就是ServiceID)
0008:80400E2F 8D542404 LEA EDX,[ESP+04]
0008:80400E33 CD2E INT 2E
0008:80400E35 C20C00 RET 000C
这样只要知道Zwxxx例程名(即System Service在内存中的线性地址),是不是就可以实现我们的目的了呢?来看看Regmon的具体实现代码吧: .
.
.
// 保存ZwOpenKey原先入口,在HookRegOpenKey中使用
RealRegOpenKey = SYSCALL( ZwOpenKey ); // 修改ZwOpenKey流程,指向新的入口,即调用ZwOpenKey时转向执行HookRegOpenKey
SYSCALL( ZwOpenKey ) = (PVOID) HookRegOpenKey;
.
.
. SYSCALL在intel平台是如下定义的:
#define SYSCALL(_function) ServiceTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]
ServiceTable->ServiceTable就是我们上面所述的 ServiceDescriptorTableEntry->ServiceTableBase(为了便于描述)。_function+1即ServiceID所在地址。整个表达式即取得_function对应的System Service的入口地址在线性内存中的位置。其它定义请参阅Regsys.c与Regsys.h!