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

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

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

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

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

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

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

观察一下使用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

{

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;

}

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

那么我们是选择记录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的地址是不正确的,为了证明一下,我写了下面的代码

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

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

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

相关推荐

窗的成语
Bet体育365提款验证

窗的成语

📅 07-04 👁️ 2791
打印机加粉方法详解(了解打印机加粉的正确操作步骤)
Bet体育365提款验证

打印机加粉方法详解(了解打印机加粉的正确操作步骤)

📅 07-01 👁️ 8380
汉字:「赑」贝贝贝 上下结构
Bet体育365提款验证

汉字:「赑」贝贝贝 上下结构

📅 06-29 👁️ 5811