公式: [[KeServiceDescriptorTable]+index(索引)*4]
例如要读取 NtOpenProcess [[KeServiceDescriptorTable]+0x7A*4]
1. 纯汇编读取
WinDbg推导公式 : dd poi[KeServiceDescriptorTable] + 0x7A*4 L 1
mul是无符号乘法
imul是带符号乘法
.cls 清屏
r ebx 读取寄存器的值
运行结果一致, 这样就读出了 NtOpenPorcess 的当前地址, 代码如下
1 ULONG SSDT_NtOpenProcess_Cur_Addr; 2 KdPrint(("驱动成功被加载...OK++++++++\n\n")); 3 //读取SSDT表中 NtOpenProcess当前地址 KeServiceDescriptorTable 4 // [[KeServiceDescriptorTable]+0x7A*4] 5 6 __asm 7 { 8 int 3 9 push ebx 10 push eax 11 mov ebx, KeServiceDescriptorTable 12 mov ebx, [ebx] 13 mov eax, 0x7A 14 imul eax, 4 // shl eax, 2 15 add ebx, eax 16 mov ebx,[ebx] 17 mov SSDT_NtOpenProcess_Cur_Addr, ebx 18 19 pop eax 20 pop ebx 21 } 22 23 KdPrint(("SSDT_NtOpenProcess_Cur_Addr=%x\n\n",SSDT_NtOpenProcess_Cur_Addr));
2. 指针方法
定义一个KeServiceDescript结构
typedef struct _ServiceDescriptorTable { PVOID ServiceTableBase; //System Service Dispatch Table 的基地址 PVOID ServiceCounterTable; //包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。 PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表 }*PServiceDescriptorTable; extern PServiceDescriptorTable KeServiceDescriptorTable;
调用指针, 获取基地址
LONG *SSDT_Adr,SSDT_NtOpenProcess_Cur_Addr,t_addr; KdPrint(("驱动成功被加载中.............................\n")); //读取SSDT表中索引值为0x7A的函数 //poi(poi(KeServiceDescriptorTable)+0x7a*4) t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase; KdPrint(("当前ServiceTableBase地址为%x \n",t_addr)); SSDT_Adr=(PLONG)(t_addr+0x7A*4); KdPrint(("当前t_addr+0x7A*4=%x \n",SSDT_Adr)); SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr; KdPrint(("当前SSDT_NtOpenProcess_Cur_Addr地址为%x \n",SSDT_NtOpenProcess_Cur_Addr));
运行截图如下:
运行环境 VS2010