与SSDT有关,但本质应该是C++指针问题
蒙飞鸿 2013-02-22 10:47:28 一般SSDT HOOK的代码如下
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;
#pragma pack()
extern "C" ServiceDescriptorTableEntry KeServiceDescriptorTable;
现在已经验证如下代码(HOOK1)能够成功HOOK:
ULONG index = *(PUCHAR)((PUCHAR)ZwOpenProcess+1);
ULONG ulBaseAddr = *(KeServiceDescriptorTable.ServiceTableBase);
PULONG SSDT_NTOpenProcess = (PULONG)(ulBaseAddr + index*4);
OldZwOpenProcess = (ZWOPENPROCESS)(*SSDT_NTOpenProcess) ;
*SSDT_NTOpenProcess = (unsigned long)NewZwOpenProcess;
index就是表索引,用SB代替KeServiceDescriptorTable.ServiceTableBase,那么HOOK1代码里通过对SB使用*取值获得表地址。
但很多SSDT HOOK的代码并不是这么计算的,而是用一个这样的宏#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PUCHAR)((PUCHAR)_function+1)]
该宏的中心应该是通过对SB[index]来获得表元素。
我的问题是不能理解SB既可以*SB取得表地址,又可以SB[index]获得表元素。想做一个简单的模拟都不成功,比如int Table[3] = {1,2,3};PUING pt = Table;那么pt[x]可以取表元素没有错,但*pt则不是表地址。如果是二级指针的话,*能得到表地址,但[]却不是表元素。