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

    xiaoxiao2022-06-29  32

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

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

    方法1

    读取c0000082寄存器

    [cpp]  view plain  copy   kd> rdmsr c0000082   msr[c0000082] = fffff800`03e82640  

     

    它记录了KiSystemCall64

    之后反汇编KiSystemCall64

    如下:

    [cpp]  view plain  copy   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

    [cpp]  view plain  copy   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

    [cpp]  view plain  copy   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 

    [cpp]  view plain  copy   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

    [cpp]  view plain  copy   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 

    下面红色标记。

    [cpp]  view plain  copy   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

     

    如下:

    [cpp]  view plain  copy   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基址:

    [cpp]  view plain  copy   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);   }  

    转载请注明原文地址: https://ju.6miu.com/read-1124988.html

    最新回复(0)