0
点赞
收藏
分享

微信扫一扫

如何动态定位SSDT表 Win10 64位 1903

草原小黄河 2022-09-17 阅读 74

对SSDT表有了解的朋友都知道在WIN64下的KeServiceDescriptorTable是没有被导出,所以我们只能动态的查找它的地址。

网上也有很多方法定位到ssdt表,其中较多的文章都是通过查找msr(c0000082)寄存器定位KiSystemCall64,然后通过搜索特诊码的方式找到KiSystemServiceRepeat,这里记录着KeServiceDescriptorTable和KeServiceDescriptorTableShadow的地址,为了方便理解这里使用WinDbg找一下KiSystemCall64和KiSystemServiceRepeat的地址

如何动态定位SSDT表 Win10 64位 1903_4s

在往下的位置可以找到KiSystemServiceRepeat这个地址,这里就可以直接看到KeServiceDescriptorTable表的地址了。

如何动态定位SSDT表 Win10 64位 1903_4s_02

那么现在问题来了,我们是否可以在win10 1903 下使用同样的方法定位到KeServiceDescriptorTable,答案是不行的(当然可能是我测试的环境的问题),rdmsr c0000082得到的地址是nt!KiSystemCall64Shadow的地址,如下图所示

如何动态定位SSDT表 Win10 64位 1903_搜索_03

看一下我们需要的地址在哪,可以明显的看出KiSystemServiceRepeat的地址在KiSystemCall64Shadow的前面,可能有的朋友就想说,既然在前面那往前搜不就行了吗?

如何动态定位SSDT表 Win10 64位 1903_i++_04

观察一下使用msr寄存器的搜索特诊码的方式,搜索的是4c 8d 15,我们使用同样的方式搜索特诊码,得到这样的结果

ULONGLONG MyGetKeServiceDescriptorTable64()
{
PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
PUCHAR i = NULL;
UCHAR b1=0,b2=0,b3=0;
ULONG templong=0;
ULONGLONG addr=0;
for(i=StartSearchAddress;i<EndSearchAddress;i++)
{
if( MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2) )
{
b1=*i;
b2=*(i+1);
b3=*(i+2);
if( b1==0x4c && b2==0x8d && b3==0x15 ) //4c8d15
{
memcpy(&templong,i+3,4);
addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
return addr;
}
}
}
return 0;
}

如何动态定位SSDT表 Win10 64位 1903_4s_05

可以从上图中看出有大量符合要求的位置被收出来了,但是这样的搜索特征码是不适合的,还有一种,通过在_strnicmp函数到KdDebuggerNotPresent之间搜索8b f8 c1 ef 07 83 e7 20 25 ff 0f 00 00的方式定位,这里通过该特诊码能够定位到指定的函数,如下图所示

如何动态定位SSDT表 Win10 64位 1903_搜索_06

那么我们是选择记录c0000082继续往上搜索特诊码8b f8 c1 ef 07 83 e7 20 25 ff 0f 00 00还是说搜索在_strnicmp函数到KdDebuggerNotPresent之间的特诊码?

ULONGLONG GetKeServiceDescriptorTable64()
{
char KiSystemServiceStart_pattern[13] =
"\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";
ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp;
ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent;
ULONGLONG i, tbl_address, b;
for (i = 0; i < CodeScanEnd - CodeScanStart; i++)
{
if (!memcmp((char*)(ULONGLONG)CodeScanStart +i,
(char*)KiSystemServiceStart_pattern,13))
{
for (b = 0; b < 50; b++)
{
tbl_address = ((ULONGLONG)CodeScanStart+i+b);
if (*(USHORT*) ((ULONGLONG)tbl_address ) == (USHORT)0x8d4c)
return ((LONGLONG)tbl_address +7) + *(LONG*)(tbl_address +3);
}
}
}
return 0;
}

由于上面的代码已经被前人写出来了,所以这里我选择借鉴前人的代码(其实就是抄),你以为这样就结束了?当然没有,如果你使用这份代码去定位那么肯定是定位不到,为什么呀?难道KiSystemServiceRepeat函数不在_strnicmp函数到KdDebuggerNotPresent之间了吗?当然不是,它肯定在,但是如果你直接这样写,你得到的_strnicmp的地址是不正确的,为了证明一下,我写了下面的代码

如何动态定位SSDT表 Win10 64位 1903_4s_07

可以从上图中看到我们得到了两个地址,第一个是直接获取函数地址,第二个是我通过导出表动态得到的地址,为了验证哪个地址是正确的,我们使用windbg看一下

如何动态定位SSDT表 Win10 64位 1903_i++_08

可以看到第一个地址定位到的是我自己的代码的位置,之后尝试在原代码中查找_strnicmp的定义,发现它直接跳到了string.h头文件中,那么可能是这种情况(我自己猜的啊,直接写这个函数的地址使用的不是内核函数导出的地址,而是调用string.h)所以直接写得到的地址是不正确的,可以尝试使用API MmGetSystemRoutineAddress得到函数的地址。

如何动态定位SSDT表 Win10 64位 1903_4s_09

这里我自己写了一个查找导出函数地址的函数,目的是由于当前虽然得到SSDT表,但是不知道哪个序号对应哪个函数呀,所以这里需要得到ntdll,之后根据ntdll的调用号让序号和函数名称对应起来



免责声明:全网优质文章转载,以作为收藏留档之用,文章均不代表本人立场!
请尊重原创作者,如需转载请标注原创作者链接



举报

相关推荐

0 条评论