ShadowSSDT保存在win32k.sys中,未导出,不是常驻内存。
采用硬编码,查到某些加载了shadowSSDT进程,所以找一个CSRSS进程,然后KeStackAttachProcess到一个有GUI线程的进程中,csrss.exe就刚好有。这个进程特征是句柄表中Portobject(type21)句柄是\\Windows\\ApiPort的PID就是就是。
然后考虑下标:下标只能硬编码,因为不是跟ssdt一样了。
首先获取SSDTSHADOW地址是通过函数KeAddSystemServiceTable来获取的。
使用这个函数的原因:
1、这个函数是已经导出的,可以在代码中直接使用。
2、这个函数里面使用了ShadowSSDT,包含了ShadowSSDT的地址。
可以使用WinDbg查看该函数代码,如下:
kd> u KeAddSystemServiceTable l 30
nt!KeAddSystemServiceTable:
83fa3008 8bff mov edi,edi
83fa300a 55 push ebp
83fa300b 8bec mov ebp,esp
83fa300d 837d1801 cmp dword ptr [ebp+18h],1
83fa3011 7760 ja nt!KeAddSystemServiceTable+0x6b (83fa3073)
83fa3013 8b4518 mov eax,dword ptr [ebp+18h]
83fa3016 c1e004 shl eax,4
83fa3019 83b8c009f88300 cmp dword ptr nt!KeServiceDescriptorTable (83f809c0)[eax],0
83fa3020 7551 jne nt!KeAddSystemServiceTable+0x6b (83fa3073)
83fa3022 8d88000af883 lea ecx,nt!KeServiceDescriptorTableShadow (83f80a00)[eax]
83fa3028 833900 cmp dword ptr [ecx],0
83fa302b 7546 jne nt!KeAddSystemServiceTable+0x6b (83fa3073)
83fa302d 837d1801 cmp dword ptr [ebp+18h],1
83fa3031 8b5508 mov edx,dword ptr [ebp+8]
83fa3034 56 push esi
83fa3035 8b7510 mov esi,dword ptr [ebp+10h]
83fa3038 57 push edi
83fa3039 8b7d14 mov edi,dword ptr [ebp+14h]
83fa303c 8911 mov dword ptr [ecx],edx
83fa303e 8b4d0c mov ecx,dword ptr [ebp+0Ch]
83fa3041 8988040af883 mov dword ptr nt!KeServiceDescriptorTableShadow+0x4 (83f80a04)[eax],ecx
83fa3047 89b0080af883 mov dword ptr nt!KeServiceDescriptorTableShadow+0x8 (83f80a08)[eax],esi
83fa304d 89b80c0af883 mov dword ptr nt!KeServiceDescriptorTableShadow+0xc (83f80a0c)[eax],edi
83fa3053 7418 je nt!KeAddSystemServiceTable+0x65 (83fa306d)
//在代码中获取
//ShadowSSDT的方式是暴力搜索,代码如下:
ULONG GetShadowTableAddress()
{
ULONG dwordatbyte, i;
PUCHAR p = (PUCHAR)KeAddSystemServiceTable;
for(i = 0; i < 0x1024; i++, p++)
{
__try
{
dwordatbyte = *(PULONG)p;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
if(MmIsAddressValid((PVOID)dwordatbyte))
{
//这里得到的以dwordatbyte为首地址的数据是否与KeServiceDescriptorTable的前16字节相同,这块没搞懂怎么就先比较地址里的值一样,再看地址不一样就是ShadowSSDT,地址里的值一样是ssdt,地址还能是Shadowssdt么
if(memcmp((PVOID)dwordatbyte, KeServiceDescriptorTable, 16) == 0)
{
//地址相同,则排除,因为要找到的是ShadowSSDT,而不是SSDT。
if((PVOID)dwordatbyte == KeServiceDescriptorTable)
continue;
return dwordatbyte;
}
}
}
return NULL;
}
找到地址,hook方式就跟其他hook类似了。
参考资料
ShadowSSDT表的获取https://blog.csdn.net/l0g1n/article/details/17569605
shadow ssdt学习笔记(一)(二)https://bbs.pediy.com/thread-56955.htm
获取Kthread结构的ServiceTable(EProcess+0xBC,win7 x86下)字段,当Kthread属于一个GUI线程时,ServiceTable的值就是KeServiceDescriptorTableShadow的地址
https://blog.csdn.net/weixin_42486644/article/details/80766003