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

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

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

如何动态定位SSDT表 Win10 64位 1903_第1张图片

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

如何动态定位SSDT表 Win10 64位 1903_第2张图片

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

如何动态定位SSDT表 Win10 64位 1903_第3张图片

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

如何动态定位SSDT表 Win10 64位 1903_第4张图片

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

如何动态定位SSDT表 Win10 64位 1903_第5张图片

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

如何动态定位SSDT表 Win10 64位 1903_第6张图片

那么我们是选择记录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看一下

如何动态定位SSDT表 Win10 64位 1903_第7张图片

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

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

你可能感兴趣的:(爱好)