Win7 64位的SSDTHOOK(1)---SSDT表的寻找

最近在学习64位驱动,涉及到了SSDT的知识,结果发现64位下的SSDT32位下的SSDT有所不同。

开始发现64位下的KeServiceDescriptorTable是未导出的函数。首先要找到KeServiceDescriptorTable的地址。

方法1

读取c0000082寄存器

 

  kd> rdmsr c0000082
  msr[c0000082] = fffff800`03e82640


 

它记录了KiSystemCall64

之后反汇编KiSystemCall64

如下:

  kd> uf KiSystemCall64
  nt!KiSystemCall64:
  fffff800`03e82640 0f01f8          swapgs
  fffff800`03e82643 654889242510000000 mov   qword ptr gs:[10h],rsp
  fffff800`03e8264c 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]
  fffff800`03e82655 6a2b            push    2Bh
  fffff800`03e82657 65ff342510000000 push    qword ptr gs:[10h]
  fffff800`03e8265f 4153            push    r11
  fffff800`03e82661 6a33            push    33h
  fffff800`03e82663 51              push    rcx
  fffff800`03e82664 498bca          mov     rcx,r10
  fffff800`03e82667 4883ec08        sub     rsp,8
  fffff800`03e8266b 55              push    rbp
  fffff800`03e8266c 4881ec58010000  sub     rsp,158h
  fffff800`03e82673 488dac2480000000 lea     rbp,[rsp+80h]
  fffff800`03e8267b 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx
  fffff800`03e82682 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi
  fffff800`03e82689 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi
  fffff800`03e82690 c645ab02        mov     byte ptr [rbp-55h],2
  fffff800`03e82694 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
  fffff800`03e8269d 0f0d8bd8010000  prefetchw [rbx+1D8h]
  fffff800`03e826a4 0fae5dac        stmxcsr dword ptr [rbp-54h]
  fffff800`03e826a8 650fae142580010000 ldmxcsr dword ptr gs:[180h]
  fffff800`03e826b1 807b0300        cmp     byte ptr [rbx+3],0
  fffff800`03e826b5 66c785800000000000 mov   word ptr [rbp+80h],0
  fffff800`03e826be 0f848c000000    je      nt!KiSystemCall64+0x110 (fffff800`03e82750)
  ---------------------------------------省略若干代码----------------------------------------------
  nt!KiSystemCall64+0x110:
  fffff800`03e82750 fb              sti
  fffff800`03e82751 48898be0010000  mov     qword ptr [rbx+1E0h],rcx
  fffff800`03e82758 8983f8010000    mov     dword ptr [rbx+1F8h],eax
  fffff800`03e8275e 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp
  fffff800`03e82765 8bf8            mov     edi,eax
  fffff800`03e82767 c1ef07          shr     edi,7
  fffff800`03e8276a 83e720          and     edi,20h
  fffff800`03e8276d 25ff0f0000      and     eax,0FFFh
  
  nt!KiSystemServiceRepeat:
  fffff800`03e82772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]
  fffff800`03e82779 4c8d1d00212300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]
  fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h
  fffff800`03e8278a 4d0f45d3        cmovne  r10,r11
  fffff800`03e8278e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
  fffff800`03e82793 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03e82a82)

 

如上红色代码。在KiSystemServiceRepeat里面找到了KeServiceDescriptorTable 

 

方法2

打开WinDbg

  kd> u nt!zwclose l10
  nt!ZwClose:
  fffff800`03e7bdc0 488bc4          mov     rax,rsp
  fffff800`03e7bdc3 fa              cli
  fffff800`03e7bdc4 4883ec10        sub     rsp,10h
  fffff800`03e7bdc8 50              push    rax
  fffff800`03e7bdc9 9c              pushfq
  fffff800`03e7bdca 6a10            push    10h
  fffff800`03e7bdcc 488d059d300000  lea     rax,[nt!KiServiceLinkage (fffff800`03e7ee70)]
  fffff800`03e7bdd3 50              push    rax
  fffff800`03e7bdd4 b80c000000      mov     eax,0Ch
  fffff800`03e7bdd9 e9e2670000      jmp     nt!KiServiceInternal (fffff800`03e825c0)
  fffff800`03e7bdde 6690            xchg    ax,ax

 

跟踪nt!KiServiceInternal

  kd> u KiServiceInternal l20
  nt!KiServiceInternal:
  fffff800`03e825c0 4883ec08        sub     rsp,8
  fffff800`03e825c4 55              push    rbp
  fffff800`03e825c5 4881ec58010000  sub     rsp,158h
  fffff800`03e825cc 488dac2480000000 lea     rbp,[rsp+80h]
  fffff800`03e825d4 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx
  fffff800`03e825db 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi
  fffff800`03e825e2 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi
  fffff800`03e825e9 fb              sti
  fffff800`03e825ea 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
  fffff800`03e825f3 0f0d8bd8010000  prefetchw [rbx+1D8h]
  fffff800`03e825fa 0fb6bbf6010000  movzx   edi,byte ptr [rbx+1F6h]
  fffff800`03e82601 40887da8        mov     byte ptr [rbp-58h],dil
  fffff800`03e82605 c683f601000000  mov     byte ptr [rbx+1F6h],0
  fffff800`03e8260c 4c8b93d8010000  mov     r10,qword ptr [rbx+1D8h]
  fffff800`03e82613 4c8995b8000000  mov     qword ptr [rbp+0B8h],r10
  fffff800`03e8261a 4c8d1d3d010000  lea     r11,[nt!KiSystemServiceStart (fffff800`03e8275e)]
  fffff800`03e82621 41ffe3          jmp     r11
  fffff800`03e82624 666666666666660f1f840000000000 nop word ptr [rax+rax]
  fffff800`03e82633 66666666660f1f840000000000 nop word ptr [rax+rax]
  nt!KiSystemCall64:
  fffff800`03e82640 0f01f8          swapgs
  fffff800`03e82643 654889242510000000 mov   qword ptr gs:[10h],rsp
  fffff800`03e8264c 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]
  fffff800`03e82655 6a2b            push    2Bh
  fffff800`03e82657 65ff342510000000 push    qword ptr gs:[10h]
  fffff800`03e8265f 4153            push    r11
  fffff800`03e82661 6a33            push    33h
  fffff800`03e82663 51              push    rcx
  fffff800`03e82664 498bca          mov     rcx,r10
  fffff800`03e82667 4883ec08        sub     rsp,8
  fffff800`03e8266b 55              push    rbp
  fffff800`03e8266c 4881ec58010000  sub     rsp,158h
  fffff800`03e82673 488dac2480000000 lea     rbp,[rsp+80h]


 

继续跟踪nt!KiSystemServiceStart 

  kd> u KiSystemServiceStart
  nt!KiSystemServiceStart:
  fffff800`03e8275e 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp
  fffff800`03e82765 8bf8            mov     edi,eax
  fffff800`03e82767 c1ef07          shr     edi,7
  fffff800`03e8276a 83e720          and     edi,20h
  fffff800`03e8276d 25ff0f0000      and     eax,0FFFh
  nt!KiSystemServiceRepeat:
  fffff800`03e82772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]
  fffff800`03e82779 4c8d1d00212300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]
  fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h


 

同样找到了KeServiceDescriptorTable 的踪影。

 

之后我们看一下KeServiceDescriptorTable

 

kd> dq KeServiceDescriptorTable
fffff800`040b4840  fffff800`03e84300 00000000`00000000
fffff800`040b4850  00000000`00000191 fffff800`03e84f8c
fffff800`040b4860  00000000`00000000 00000000`00000000
fffff800`040b4870  00000000`00000000 00000000`00000000
fffff800`040b4880  fffff800`03e84300 00000000`00000000
fffff800`040b4890  00000000`00000191 fffff800`03e84f8c
fffff800`040b48a0  fffff960`001b1f00 00000000`00000000
fffff800`040b48b0  00000000`0000033b fffff960`001b3c1c


 

因为根据公式:

newAddress-oldAddress-7(指令长度)=bytearray

 

SSDT = fffff800`03e82772 + 237847 + 7 = fffff800`040b4840

 

所以KeServiceDescriptorTable基地址:fffff800`040b4840

 

我们编写程序的时候可以匹配一下4c8d15c7202300  这个特种就可以找到KeServiceDescriptorTable了。

 

接下来就演示算出SSDT表中第一个函数(也就是INDEX=0)的地址(这里为NtMapUserPhysicalPagesScatter),之后的以此类推就可以了。

64位和32位算法有所不同,64位需要得到 **KeServiceDescriptorTable = 040d9a00 

下面红色标记。

  kd> dd fffff800`03e84300
  fffff800`03e84300  040d9a00 02f55c00 fff6ea00 02e87805
  fffff800`03e84310  031a4a06 03116a05 02bb9901 02b4f200
  fffff800`03e84320  0312cc40 03dd7400 02c84700 02e7d100
  fffff800`03e84330  02f68100 02e02301 02dd0601 02d96100
  fffff800`03e84340  02df4602 02f18600 02ad0500 02cefe01
  fffff800`03e84350  02d01d02 02f69902 03101101 0323ca01
  fffff800`03e84360  0455c305 02ed29c0 02b2e703 ffec1d00
  fffff800`03e84370  043c2800 02f51040 02c52c01 03126c00
  


 

公式:ServiceTableBase[Index] >> 4 + ServiceTableBase

    ServiceTableBase[Index] = ServiceTableBase + Index * 4

即:

040d9a00 >> 4 = 40D9A0 + *KeServiceDescriptorTable = FFFFF80004291CA0

 

如下:

  kd> u FFFFF80004291CA0
   nt!NtMapUserPhysicalPagesScatter:
    fffff800`04291ca0 48895c2408      mov     qword ptr [rsp+8],rbx
  fffff800`04291ca5 4c89442418      mov     qword ptr [rsp+18h],r8
  fffff800`04291caa 55              push    rbp
  fffff800`04291cab 56              push    rsi
  fffff800`04291cac 57              push    rdi
  fffff800`04291cad 4154            push    r12
  fffff800`04291caf 4155            push    r13
  fffff800`04291cb1 4156            push    r14


 

对比XT

 

 

结果正确。


接下来用C实现以下找SSDT基址:

VOID GetSSDTBaseAddr()
{
	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)
			{
				memcpy(&templong,i+3,4);
				//核心部分
				//kd> db fffff800`03e8b772
				//fffff800`03e8b772  4c 8d 15 c7 20 23 00 4c-8d 1d 00 21 23 00 f7 83  L... #.L...!#...
				//templong = 002320c7 ,i = 03e8b772, 7为指令长度
				addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
				break;
			}
		}
	}
	DbgPrint("b1 = %0x\n",b1);
	DbgPrint("b2 = %0x\n",b2);
	DbgPrint("b3 = %0x",b3);
	DbgPrint("templong = %0x\n",templong);
	DbgPrint("addr = %0x\n",addr);
}


 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值