【原創】WINDOWS 64位SSDT定位思路

來源:互聯網
上載者:User

在32位Windows中我們有很多定位SSDT的方法,最直接的就是利用匯出符號來找到SSDT。再有就是通過在nt!KeAddSystemServiceTable函數中進行反組譯碼搜尋。可是在64位WINDOWS中這兩種方法都行不通。在64位Windows中不在匯出SSDT了。這樣要HOOK SSDT表就出現了第一個問題如何找到它?我想了三種思路。
思路1:
對每種版本的系統確定一個ntoskrnl到SSDT的寫入程式碼位移。呵呵,這種方法可能比較傻但最簡單直接有效。就是維護起來比較非常麻煩,要對每一個版本進單獨處理,如果不同補丁版本有變化也要處理。
思路2:
64位WINDOWS中存放著每個服務常式的入口位移(這個位移是相對於SSDT的開始地址的)。我取一個一般不被HOOK的服務常式入口位移,然後從ntoskrnl的開始地址一直搜尋到結束來尋找這四個位元組,然後根據服務常式的索引定位到SSDT的開始位置。可能對不同版本的作業系統其位移和索引是不同的需要分別進行處理,但是相比第一種思路要通用一些。
思路3:
還是利用反組譯碼的方法。後來我想能不能映像搜尋到SSDT的地址。
kd> dq nt!KeServiceDescriptorTable
fffff800`03eab840  fffff800`03c75b00 00000000`00000000
fffff800`03eab850  00000000`00000191 fffff800`03c7678c
fffff800`03eab860  00000000`00000000 00000000`00000000
fffff800`03eab870  00000000`00000000 00000000`00000000
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
kd> lm m nt
start             end                 module name
fffff800`03c03000 fffff800`041e0000   nt         (pdb symbols)
kd> s -q fffff800`03c03000 l600000 fffff800`03eab840
很不幸我沒有找到任何相關的資訊。呵呵,但是我賊心不是死,相信肯定在某處會有引用的。於是我搜尋了一下所有名稱中含有Service單詞的符號。
kd> x nt!Ki*Service*
fffff800`03c73e40 nt!KiServiceInternal = <no type information>
fffff800`03c7415b nt!KiSystemServiceExit = <no type information>
fffff800`03c73fde nt!KiSystemServiceStart = <no type information>
fffff800`03c76788 nt!KiServiceLimit = <no type information>
fffff800`03c73b00 nt!KiDebugServiceTrap = <no type information>
fffff800`03c74140 nt!KiSystemServiceCopyEnd = <no type information>
fffff800`03c75b00 nt!KiServiceTable = <no type information>
fffff800`03c74037 nt!KiSystemServiceGdiTebAccess = <no type information>
fffff800`03c73ff2 nt!KiSystemServiceRepeat = <no type information>

fffff800`03c740d0 nt!KiSystemServiceCopyStart = <no type information>
fffff800`03c706f0 nt!KiServiceLinkage = <no type information>
fffff800`03c73d40 nt!KiSystemServiceHandler = <no type information>
終於在nt!KiSystemServiceRepeat 中找到SSDT的資訊。
nt!KiSystemServiceRepeat:
fffff800`03c73ff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`03eab840)]
fffff800`03c73ff9 4c8d1d80782300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`03eab880)]
fffff800`03c74000 f7830001000080000000 test dword ptr [rbx+100h],80h
fffff800`03c7400a 4d0f45d3        cmovne  r10,r11
fffff800`03c7400e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
fffff800`03c74013 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03c74302)
fffff800`03c74019 4e8b1417        mov     r10,qword ptr [rdi+r10]
fffff800`03c7401d 4d631c82        movsxd  r11,dword ptr [r10+rax*4]
但是一個新的問題也同時產生了,nt!KiSystemServiceRepeat並不是系統的一個匯出函數。那我怎麼找到它呢?後來一想雖然它不匯出但應該至少存在一條從外部到它的一個調用路徑吧!那我就通過這條路徑找到它不就行了。想到此就對它下了個斷點看看都是誰會調用它。結果和我想的一樣,不過發現我真是一個菜鳥,找到SSDT值太高興竟沒有仔細看它的彙編代碼。nt!KiSystemServiceRepeat就是完成根據調用號從SSDT中獲得服務常式入口並調用的。那就說每一個ZwXXX類的函數都會調用到它,而Zw類的函數是系統匯出的這樣我們可以通過任何一個Zw類的函數來找到nt!KiSystemServiceRepeat從而定位到SSDT。於是我手工嘗試了一下。下面是嘗試的過程。
kd> u nt!ZwClose l20
nt!ZwClose:
fffff800`03c6d640 488bc4          mov     rax,rsp
fffff800`03c6d643 fa              cli
fffff800`03c6d644 4883ec10        sub     rsp,10h
fffff800`03c6d648 50              push    rax
fffff800`03c6d649 9c              pushfq
fffff800`03c6d64a 6a10            push    10h
fffff800`03c6d64c 488d059d300000  lea     rax,[nt!KiServiceLinkage (fffff800`03c706f0)]
fffff800`03c6d653 50              push    rax
fffff800`03c6d654 b80c000000      mov     eax,0Ch
fffff800`03c6d659 e9e2670000      jmp     nt!KiServiceInternal (fffff800`03c73e40)
fffff800`03c6d65e 6690            xchg    ax,ax
在ZwClose中(其它類似)跳轉到了nt!KiServiceInternal 我們再跟蹤nt!KiServiceInternal 
nt!KiServiceInternal:
fffff800`03c73e40 4883ec08        sub     rsp,8
fffff800`03c73e44 55              push    rbp
fffff800`03c73e45 4881ec58010000  sub     rsp,158h
fffff800`03c73e4c 488dac2480000000 lea     rbp,[rsp+80h]
fffff800`03c73e54 48899dc0000000  mov     qword ptr [rbp+0C0h],rbx
fffff800`03c73e5b 4889bdc8000000  mov     qword ptr [rbp+0C8h],rdi
fffff800`03c73e62 4889b5d0000000  mov     qword ptr [rbp+0D0h],rsi
fffff800`03c73e69 fb              sti
fffff800`03c73e6a 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
fffff800`03c73e73 0f0d8bd8010000  prefetchw [rbx+1D8h]
fffff800`03c73e7a 0fb6bbf6010000  movzx   edi,byte ptr [rbx+1F6h]
fffff800`03c73e81 40887da8        mov     byte ptr [rbp-58h],dil
fffff800`03c73e85 c683f601000000  mov     byte ptr [rbx+1F6h],0
fffff800`03c73e8c 4c8b93d8010000  mov     r10,qword ptr [rbx+1D8h]
fffff800`03c73e93 4c8995b8000000  mov     qword ptr [rbp+0B8h],r10
fffff800`03c73e9a 4c8d1d3d010000  lea     r11,[nt!KiSystemServiceStart (fffff800`03c73fde)]
fffff800`03c73ea1 41ffe3          jmp     r11
fffff800`03c73ea4 666666666666660f1f840000000000 nop word ptr [rax+rax]
fffff800`03c73eb3 66666666660f1f840000000000 nop word ptr [rax+rax]

在這個函數中又跳轉到了nt!KiSystemServiceStart,這裡4c8d1d3d010000 這條指令需要參考一下x64彙編中有關Rex.w首碼及Mod r/m定址方面的知識來解釋這個位移。在這裡就是fffff800`03c73ea1+013d就是nt!KiSystemServiceStart入口地址。接下來再從這個地址開始反組譯碼。
nt!KiSystemServiceStart:
fffff800`03c73fde 4889a3d8010000  mov     qword ptr [rbx+1D8h],rsp
fffff800`03c73fe5 8bf8            mov     edi,eax
fffff800`03c73fe7 c1ef07          shr     edi,7
fffff800`03c73fea 83e720          and     edi,20h
fffff800`03c73fed 25ff0f0000      and     eax,0FFFh
nt!KiSystemServiceRepeat:
fffff800`03c73ff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable (fffff800`03eab840)]
fffff800`03c73ff9 4c8d1d80782300  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff800`03eab880)]
fffff800`03c74000 f7830001000080000000 test dword ptr [rbx+100h],80h
fffff800`03c7400a 4d0f45d3        cmovne  r10,r11
fffff800`03c7400e 423b441710      cmp     eax,dword ptr [rdi+r10+10h]
fffff800`03c74013 0f83e9020000    jae     nt!KiSystemServiceExit+0x1a7 (fffff800`03c74302)
fffff800`03c74019 4e8b1417        mov     r10,qword ptr [rdi+r10]
fffff800`03c7401d 4d631c82        movsxd  r11,dword ptr [r10+rax*4]
fffff800`03c74021 498bc3          mov     rax,r11
fffff800`03c74024 49c1fb04        sar     r11,4
fffff800`03c74028 4d03d3          add     r10,r11
fffff800`03c7402b 83ff20          cmp     edi,20h
fffff800`03c7402e 7550            jne     nt!KiSystemServiceGdiTebAccess+0x49 (fffff800`03c74080)
fffff800`03c74030 4c8b9bb8000000  mov     r11,qword ptr [rbx+0B8h]
終於找到我們要找到函數了,4c8d1547782300,4c8d1d80782300根據這兩條指令我就可以定位到SSDT的位置了。終於撥雲見日了。這兩條指令都加了REX.W首碼的根據具體欄位的意義解釋它就可找到SSDT,4c8d1547782300這條指令的64立即數定址應該是fffff800`03c73ff9+237847這樣來擴充,就是RIP+位移。相類似4c8d1d80782300指令中的立即數應該被擴充成fffff800`03c74000+237880,通過DQ命令查看就是SSDT的內容。
kd> dq fffff800`03c74000+237880
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
fffff800`03eab8c0  00000000`7771fdd6 00000000`00000000
fffff800`03eab8d0  fffff800`00a01400 fffff800`00a013b0
fffff800`03eab8e0  00000000`00000002 00000000`00005bdb
fffff800`03eab8f0  00000000`00023f05 00000000`00000000
kd> dq nt!KeServiceDescriptorTableShadow
fffff800`03eab880  fffff800`03c75b00 00000000`00000000
fffff800`03eab890  00000000`00000191 fffff800`03c7678c
fffff800`03eab8a0  fffff960`00111c00 00000000`00000000
fffff800`03eab8b0  00000000`0000033b fffff960`0011391c
fffff800`03eab8c0  00000000`7771fdd6 00000000`00000000
fffff800`03eab8d0  fffff800`00a01400 fffff800`00a013b0
fffff800`03eab8e0  00000000`00000002 00000000`00005bdb
fffff800`03eab8f0  00000000`00023f05 00000000`00000000
兩種方法找到位置一樣。我這裡的輸出都針對WIN7 64位系統的調用,通過對2003進行調試發現這樣的方法也適用。因為沒有暫時沒有其它版本作業系統。在其它作業系統上的適用性怎麼樣就無從知道了。個人推測XP,VISTA也應該差不多但需要事實證明。不過Win7與2003中SSDT表項內容略有不同,雖然都是四個節最後四位是常式的參數個數,但在2003上位移的計算是SSDT基址+表項值&0xFFFFFFF0,而win7上則變成了SSDT基址+表項值>>4。如果HOOK表項還是要做一個分別對待。上面闡述如有錯誤請個位大俠多多指教,小弟不勝感激。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.