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

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

http://blog.csdn.net/zfdyq0/article/details/26515019


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

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

方法1

读取c0000082寄存器

 

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> rdmsr c0000082  
  2. msr[c0000082] = fffff800`03e82640  


 

它记录了KiSystemCall64

之后反汇编KiSystemCall64

如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> uf KiSystemCall64  
  2. nt!KiSystemCall64:  
  3. fffff800`03e82640 0f01f8          swapgs  
  4. fffff800`03e82643 654889242510000000 mov   qword ptr gs:[10h],rsp  
  5. fffff800`03e8264c 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]  
  6. fffff800`03e82655 6a2b            push    2Bh  
  7. fffff800`03e82657 65ff342510000000 push    qword ptr gs:[10h]  
  8. fffff800`03e8265f 4153            push    r11  
  9. fffff800`03e82661 6a33            push    33h  
  10. fffff800`03e82663 51              push    rcx  
  11. fffff800`03e82664 498bca          mov     rcx,r10  
  12. fffff800`03e82667 4883ec08        sub     rsp,8  
  13. fffff800`03e8266b 55              push    rbp  
  14. fffff800`03e8266c 4881ec58010000  sub     rsp,158h  
  15. fffff800`03e82673 488dac2480000000 lea     rbp,[rsp+80h]  
  16. fffff800`03e8267b 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx  
  17. fffff800`03e82682 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi  
  18. fffff800`03e82689 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi  
  19. fffff800`03e82690 c645ab02        mov     byte ptr [rbp-55h],2  
  20. fffff800`03e82694 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]  
  21. fffff800`03e8269d 0f0d8bd8010000  prefetchw [rbx+1D8h]  
  22. fffff800`03e826a4 0fae5dac        stmxcsr dword ptr [rbp-54h]  
  23. fffff800`03e826a8 650fae142580010000 ldmxcsr dword ptr gs:[180h]  
  24. fffff800`03e826b1 807b0300        cmp     byte ptr [rbx+3],0  
  25. fffff800`03e826b5 66c785800000000000 mov   word ptr [rbp+80h],0  
  26. fffff800`03e826be 0f848c000000    je      nt!KiSystemCall64+0x110 (fffff800`03e82750)  
  27. ---------------------------------------省略若干代码----------------------------------------------  
  28. nt!KiSystemCall64+0x110:  
  29. fffff800`03e82750 fb              sti  
  30. fffff800`03e82751 48898be0010000  mov     qword ptr [rbx+1E0h],rcx  
  31. fffff800`03e82758 8983f8010000    mov     dword ptr [rbx+1F8h],eax  
  32. fffff800`03e8275e 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp  
  33. fffff800`03e82765 8bf8            mov     edi,eax  
  34. fffff800`03e82767 c1ef07          shr     edi,7  
  35. fffff800`03e8276a 83e720          and     edi,20h  
  36. fffff800`03e8276d 25ff0f0000      and     eax,0FFFh  
  37.   
  38. nt!KiSystemServiceRepeat:  
  39. fffff800`03e82772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]  
  40. fffff800`03e82779 4c8d1d00212300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]  
  41. fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h  
  42. fffff800`03e8278a 4d0f45d3        cmovne  r10,r11  
  43. fffff800`03e8278e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]  
  44. fffff800`03e82793 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03e82a82)  

 

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

 

方法2

打开WinDbg

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> u nt!zwclose l10  
  2. nt!ZwClose:  
  3. fffff800`03e7bdc0 488bc4          mov     rax,rsp  
  4. fffff800`03e7bdc3 fa              cli  
  5. fffff800`03e7bdc4 4883ec10        sub     rsp,10h  
  6. fffff800`03e7bdc8 50              push    rax  
  7. fffff800`03e7bdc9 9c              pushfq  
  8. fffff800`03e7bdca 6a10            push    10h  
  9. fffff800`03e7bdcc 488d059d300000  lea     rax,[nt!KiServiceLinkage (fffff800`03e7ee70)]  
  10. fffff800`03e7bdd3 50              push    rax  
  11. fffff800`03e7bdd4 b80c000000      mov     eax,0Ch  
  12. fffff800`03e7bdd9 e9e2670000      jmp     nt!KiServiceInternal (fffff800`03e825c0)  
  13. fffff800`03e7bdde 6690            xchg    ax,ax  

 

跟踪nt!KiServiceInternal

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> u KiServiceInternal l20  
  2. nt!KiServiceInternal:  
  3. fffff800`03e825c0 4883ec08        sub     rsp,8  
  4. fffff800`03e825c4 55              push    rbp  
  5. fffff800`03e825c5 4881ec58010000  sub     rsp,158h  
  6. fffff800`03e825cc 488dac2480000000 lea     rbp,[rsp+80h]  
  7. fffff800`03e825d4 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx  
  8. fffff800`03e825db 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi  
  9. fffff800`03e825e2 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi  
  10. fffff800`03e825e9 fb              sti  
  11. fffff800`03e825ea 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]  
  12. fffff800`03e825f3 0f0d8bd8010000  prefetchw [rbx+1D8h]  
  13. fffff800`03e825fa 0fb6bbf6010000  movzx   edi,byte ptr [rbx+1F6h]  
  14. fffff800`03e82601 40887da8        mov     byte ptr [rbp-58h],dil  
  15. fffff800`03e82605 c683f601000000  mov     byte ptr [rbx+1F6h],0  
  16. fffff800`03e8260c 4c8b93d8010000  mov     r10,qword ptr [rbx+1D8h]  
  17. fffff800`03e82613 4c8995b8000000  mov     qword ptr [rbp+0B8h],r10  
  18. fffff800`03e8261a 4c8d1d3d010000  lea     r11,[nt!KiSystemServiceStart (fffff800`03e8275e)]  
  19. fffff800`03e82621 41ffe3          jmp     r11  
  20. fffff800`03e82624 666666666666660f1f840000000000 nop word ptr [rax+rax]  
  21. fffff800`03e82633 66666666660f1f840000000000 nop word ptr [rax+rax]  
  22. nt!KiSystemCall64:  
  23. fffff800`03e82640 0f01f8          swapgs  
  24. fffff800`03e82643 654889242510000000 mov   qword ptr gs:[10h],rsp  
  25. fffff800`03e8264c 65488b2425a8010000 mov   rsp,qword ptr gs:[1A8h]  
  26. fffff800`03e82655 6a2b            push    2Bh  
  27. fffff800`03e82657 65ff342510000000 push    qword ptr gs:[10h]  
  28. fffff800`03e8265f 4153            push    r11  
  29. fffff800`03e82661 6a33            push    33h  
  30. fffff800`03e82663 51              push    rcx  
  31. fffff800`03e82664 498bca          mov     rcx,r10  
  32. fffff800`03e82667 4883ec08        sub     rsp,8  
  33. fffff800`03e8266b 55              push    rbp  
  34. fffff800`03e8266c 4881ec58010000  sub     rsp,158h  
  35. fffff800`03e82673 488dac2480000000 lea     rbp,[rsp+80h]  


 

继续跟踪nt!KiSystemServiceStart 

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> u KiSystemServiceStart  
  2. nt!KiSystemServiceStart:  
  3. fffff800`03e8275e 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp  
  4. fffff800`03e82765 8bf8            mov     edi,eax  
  5. fffff800`03e82767 c1ef07          shr     edi,7  
  6. fffff800`03e8276a 83e720          and     edi,20h  
  7. fffff800`03e8276d 25ff0f0000      and     eax,0FFFh  
  8. nt!KiSystemServiceRepeat:  
  9. fffff800`03e82772 4c8d15c7202300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`040b4840)]  
  10. fffff800`03e82779 4c8d1d00212300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`040b4880)]  
  11. fffff800`03e82780 f7830001000080000000 test dword ptr [rbx+100h],80h  


 

同样找到了KeServiceDescriptorTable 的踪影。

 

之后我们看一下KeServiceDescriptorTable

 

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> dq KeServiceDescriptorTable  
  2. fffff800`040b4840  fffff800`03e84300 00000000`00000000  
  3. fffff800`040b4850  00000000`00000191 fffff800`03e84f8c  
  4. fffff800`040b4860  00000000`00000000 00000000`00000000  
  5. fffff800`040b4870  00000000`00000000 00000000`00000000  
  6. fffff800`040b4880  fffff800`03e84300 00000000`00000000  
  7. fffff800`040b4890  00000000`00000191 fffff800`03e84f8c  
  8. fffff800`040b48a0  fffff960`001b1f00 00000000`00000000  
  9. 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 

下面红色标记。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> dd fffff800`03e84300  
  2. fffff800`03e84300  040d9a00 02f55c00 fff6ea00 02e87805  
  3. fffff800`03e84310  031a4a06 03116a05 02bb9901 02b4f200  
  4. fffff800`03e84320  0312cc40 03dd7400 02c84700 02e7d100  
  5. fffff800`03e84330  02f68100 02e02301 02dd0601 02d96100  
  6. fffff800`03e84340  02df4602 02f18600 02ad0500 02cefe01  
  7. fffff800`03e84350  02d01d02 02f69902 03101101 0323ca01  
  8. fffff800`03e84360  0455c305 02ed29c0 02b2e703 ffec1d00  
  9. fffff800`03e84370  043c2800 02f51040 02c52c01 03126c00  


 

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

    ServiceTableBase[Index] = ServiceTableBase + Index * 4

即:

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

 

如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> u FFFFF80004291CA0  
  2.  nt!NtMapUserPhysicalPagesScatter:  
  3.   fffff800`04291ca0 48895c2408      mov     qword ptr [rsp+8],rbx  
  4. fffff800`04291ca5 4c89442418      mov     qword ptr [rsp+18h],r8  
  5. fffff800`04291caa 55              push    rbp  
  6. fffff800`04291cab 56              push    rsi  
  7. fffff800`04291cac 57              push    rdi  
  8. fffff800`04291cad 4154            push    r12  
  9. fffff800`04291caf 4155            push    r13  
  10. fffff800`04291cb1 4156            push    r14  


 

对比XT

 

 

结果正确。


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

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. VOID GetSSDTBaseAddr()  
  2. {  
  3.     PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);  
  4.     PUCHAR EndSearchAddress = StartSearchAddress + 0x500;  
  5.     PUCHAR i = NULL;  
  6.     UCHAR b1 = 0, b2 = 0, b3 = 0;  
  7.     ULONG templong = 0;  
  8.     ULONGLONG addr = 0;  
  9.     for (i = StartSearchAddress;i<EndSearchAddress;i++)  
  10.     {  
  11.         if (MmIsAddressValid(i) && MmIsAddressValid(i+1) && MmIsAddressValid(i+2))  
  12.         {  
  13.             b1 = *(i);  
  14.             b2 = *(i+1);  
  15.             b3 = *(i+2);  
  16.             if (b1==0x4c && b2==0x8d && b3==0x15)  
  17.             {  
  18.                 memcpy(&templong,i+3,4);  
  19.                 //核心部分  
  20.                 //kd> db fffff800`03e8b772  
  21.                 //fffff800`03e8b772  4c 8d 15 c7 20 23 00 4c-8d 1d 00 21 23 00 f7 83  L... #.L...!#...  
  22.                 //templong = 002320c7 ,i = 03e8b772, 7为指令长度  
  23.                 addr = (ULONGLONG)templong + (ULONGLONG)i + 7;  
  24.                 break;  
  25.             }  
  26.         }  
  27.     }  
  28.     DbgPrint("b1 = %0x\n",b1);  
  29.     DbgPrint("b2 = %0x\n",b2);  
  30.     DbgPrint("b3 = %0x",b3);  
  31.     DbgPrint("templong = %0x\n",templong);  
  32.     DbgPrint("addr = %0x\n",addr);  
  33. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值