刚刚解决了EPROCESS、ETHREAD的硬编码查询问题,又遭遇了系统服务号的硬编码。
刚找到方法如下。
===
环境:win7+windbg+livekd
===
0: kd> u ZwCreateProcessEx
nt!ZwCreateProcessEx:8427eff4 b850000000 mov eax,50h <---------注意啦,这个就是系统服务号的硬编码。8427eff9 8d542404 lea edx,[esp+4]8427effd 9c pushfd8427effe 6a08 push 88427f000 e849220000 call nt!KiSystemService (8428124e) <--------8427f005 c22400 ret 24hnt!ZwCreateProfile:8427f008 b851000000 mov eax,51h8427f00d 8d542404 lea edx,[esp+4]KeSystemServiceDescriptorTable->ServiceTableBase+服务号 就是该函数在系统服务描述符表中的位置。
KeServiceDescriptorTable:是由内核(Ntoskrnl.exe)导出的一个表,这个表是访问SSDT的关键,具体结构是
typedef struct ServiceDescriptorTable { PVOID ServiceTableBase;PVOID ServiceCounterTable(0);unsigned int NumberOfServices;PVOID ParamTableBase;}==ServiceTableBase :SSDT 的基地址。
== NumberOfServices : ServiceTableBase 描述的服务的数目。 == ServiceCounterTable :此域用于操作系统的 checked builds,包含着 SSDT 中每个服务被调用次数的计数器。这个计数器由 INT 2Eh 处理程序 (KiSystemService)更新。 ==ParamTableBase 包含每个系统服务参数字节数表的基地址(就是系统服务号)。上面的汇编代码就是把参数压栈的过程。==================================
刚刚看雪上看到,还有这样用的:
#define SYSTEMSERVICE(_function)KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
调用OldNtCreateFile=(NTOPENKEY)(SYSTEMSERVICE(ZwOpenKey));也就是变成了OldNtCreateFile=KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)ZwOpenKey+1)]原理如下:
0: kd> u ZwOpenKey
nt!ZwOpenKey:8427f7ec b8b6000000 mov eax,0B6h| |_ServiceID
|_机器码(其中第二字节即ZwOpenKey线性地址加一处就是ServiceID)8427f7f1 8d542404 lea edx,[esp+4]8427f7f5 9c pushfd8427f7f6 6a08 push 88427f7f8 e8511a0000 call nt!KiSystemService (8428124e)8427f7fd c20c00 ret 0Chnt!ZwOpenKeyEx:8427f800 b8b7000000 mov eax,0B7h8427f805 8d542404 lea edx,[esp+4](还不如硬编码呢。。)