實際上我以爲這玩意就是個PE文件的導出表:html
kd> u nt!ZwQuerySystemInformation nt!ZwQuerySystemInformation: 81f82778 b89a000000 mov eax,9Ah 81f8277d 8d542404 lea edx,[esp+4] 81f82781 9c pushfd 81f82782 6a08 push 8 81f82784 e8dc010100 call nt!ExfUnblockPushLock+0x12c5 (81f92965) 81f82789 c21000 ret 10h nt!ZwQuerySystemEnvironmentValueEx: 81f8278c b89b000000 mov eax,9Bh 81f82791 8d542404 lea edx,[esp+4] kd> dd KeServiceDescriptorTable 820cf2c0 81f843b8 00000000 000001b9 81f84aa0 820cf2d0 00000000 00000000 00000000 00000000 820cf2e0 a3cd3fff 00000001 ffffffff 81f980f7 820cf2f0 00000000 00000000 00000001 00000000 820cf300 9084246c 01d435c6 00000000 00000000 820cf310 86140d80 82e89000 8603eaf8 00001000 820cf320 00010000 7ffeffff 80000000 83600000 820cf330 7fff0000 8296a000 8602c010 00001c1d kd> dd 81f843b8 81f843b8 81eac66e 81ec934e 821a0d06 81e99a00 81f843c8 82114dca 82323a50 8218a016 8210e0a0 81f843d8 8223a612 8223a612 81f1b730 821c77e0 81f843e8 8232f409 821c7690 821a1064 822efc5c 81f843f8 82185fd4 8235cf90 8218cb92 821b7e32 81f84408 8218909e 821890c0 81f49620 82193298 81f84418 821767f8 8220a48a 8223a20a 822fe2b4 81f84428 82321564 82375032 81e91fd0 8211c150 kd> u 81eac66e nt!RtlLookupEntryHashTable+0xbe: 81eac66e 8bff mov edi,edi 81eac670 55 push ebp 81eac671 8bec mov ebp,esp 81eac673 8b4d08 mov ecx,dword ptr [ebp+8] 81eac676 33c0 xor eax,eax 81eac678 50 push eax 81eac679 ff7524 push dword ptr [ebp+24h] 81eac67c 33d2 xor edx,edx kd> dd 81f84620 //9Ah*4+81f843b8 81f84620 8213d7b0 8220cf4e 823741af 82189160 81f84630 82375be1 82137e46 8213f6c0 821a8a9a 81f84640 822fb5ce 8223ac9e 8218c5c4 822da5fd 81f84650 822da3d9 82182e10 823780a5 821044c2 81f84660 82179f32 821d97a0 822fa322 821e9db6 81f84670 8219ff28 820728d3 81e7d36c 81e7d366 81f84680 8213f970 8210ff80 81e7d360 821bcd60 81f84690 8232388e 8215acac 821c9870 81e7d35a kd> u 8213d7b0 nt!NtQuerySystemInformation: 8213d7b0 8bff mov edi,edi 8213d7b2 55 push ebp 8213d7b3 8bec mov ebp,esp 8213d7b5 8b4d08 mov ecx,dword ptr [ebp+8] 8213d7b8 83f94a cmp ecx,4Ah 8213d7bb 7c1c jl nt!NtQuerySystemInformation+0x29 (8213d7d9) 8213d7bd 83f953 cmp ecx,53h 8213d7c0 7d17 jge nt!NtQuerySystemInformation+0x29 (8213d7d9) x64以下: 計算公式以下: Ssdt爲KeServiceDescriptorTable地址,Index爲索引值 FunAddr =ssdt+(ssdt+4 * Index)>>4 0: kd> uf nt!zwopenprocess Flow analysis was incomplete, some code may be missing nt!ZwOpenProcess: fffff802`7fd68370 488bc4 mov rax,rsp fffff802`7fd68373 fa cli fffff802`7fd68374 4883ec10 sub rsp,10h fffff802`7fd68378 50 push rax fffff802`7fd68379 9c pushfq fffff802`7fd6837a 6a10 push 10h fffff802`7fd6837c 488d05fd600000 lea rax,[nt!KiServiceLinkage (fffff802`7fd6e480)] fffff802`7fd68383 50 push rax fffff802`7fd68384 b826000000 mov eax,26h fffff802`7fd68389 e9b2d50000 jmp nt!KiServiceInternal (fffff802`7fd75940) Branch nt!KiServiceInternal: fffff802`7fd75940 4883ec08 sub rsp,8 fffff802`7fd75944 55 push rbp fffff802`7fd75945 4881ec58010000 sub rsp,158h fffff802`7fd7594c 488dac2480000000 lea rbp,[rsp+80h] fffff802`7fd75954 48899dc0000000 mov qword ptr [rbp+0C0h],rbx fffff802`7fd7595b 4889bdc8000000 mov qword ptr [rbp+0C8h],rdi fffff802`7fd75962 4889b5d0000000 mov qword ptr [rbp+0D0h],rsi fffff802`7fd75969 fb sti fffff802`7fd7596a 65488b1c2588010000 mov rbx,qword ptr gs:[188h] fffff802`7fd75973 0f0d8b90000000 prefetchw [rbx+90h] fffff802`7fd7597a 0fb6bb32020000 movzx edi,byte ptr [rbx+232h] fffff802`7fd75981 40887da8 mov byte ptr [rbp-58h],dil fffff802`7fd75985 c6833202000000 mov byte ptr [rbx+232h],0 fffff802`7fd7598c 4c8b9390000000 mov r10,qword ptr [rbx+90h] fffff802`7fd75993 4c8995b8000000 mov qword ptr [rbp+0B8h],r10 fffff802`7fd7599a 4c8d1d4f010000 lea r11,[nt!KiSystemServiceStart (fffff802`7fd75af0)] fffff802`7fd759a1 41ffe3 jmp r11 0: kd> dq KeServiceDescriptorTable fffff802`7ffe0740 fffff802`7ff23020 00000000`00000000 fffff802`7ffe0750 00000000`000001b9 fffff802`7ff23dec fffff802`7ffe0760 00000000`00000000 00000000`00000000 fffff802`7ffe0770 00000000`00000000 00000000`00000000 fffff802`7ffe0780 00000000`00000000 00000000`00000000 fffff802`7ffe0790 00000000`009c19c2 00007ffe`8dd556f0 fffff802`7ffe07a0 ffffe001`015763f0 ffffe001`01578c60 fffff802`7ffe07b0 00000000`00000000 00000000`00000000 0: kd> dd fffff802`7ff23020+98h //26h*4=98h fffff802`7ff230b8 0102d600 fdc03501 010bbc06 019ce7c7 fffff802`7ff230c8 0108c240 01a97f01 018e1600 03df8400 fffff802`7ff230d8 022720c5 014d4901 020bfe00 0211b180 fffff802`7ff230e8 01388e02 017a9b42 00f5f900 01d73707 fffff802`7ff230f8 01040800 02118100 03df6e41 0185b146 fffff802`7ff23108 02264f81 021a66c0 01450003 020cf900 fffff802`7ff23118 0208d000 0128e601 0216e140 019f3a02 fffff802`7ff23128 014d02c2 fe48c500 02460600 021eb2c1 0: kd> u fffff802`7ff23020+0102d60 //0102d600>>4=0102d60 nt!NtOpenProcess: fffff802`80025d80 4883ec38 sub rsp,38h fffff802`80025d84 65488b042588010000 mov rax,qword ptr gs:[188h] fffff802`80025d8d 440fb69032020000 movzx r10d,byte ptr [rax+232h] fffff802`80025d95 4488542428 mov byte ptr [rsp+28h],r10b fffff802`80025d9a 4488542420 mov byte ptr [rsp+20h],r10b fffff802`80025d9f e80c000000 call nt!PsOpenProcess (fffff802`80025db0) fffff802`80025da4 4883c438 add rsp,38h fffff802`80025da8 c3 ret 測試修改SSDT後是否藍屏(patch guard做用): 0: kd> uf nt!ZwQuerySystemInformation Flow analysis was incomplete, some code may be missing nt!ZwQuerySystemInformation: fffff802`c5fdc570 488bc4 mov rax,rsp fffff802`c5fdc573 fa cli fffff802`c5fdc574 4883ec10 sub rsp,10h fffff802`c5fdc578 50 push rax fffff802`c5fdc579 9c pushfq fffff802`c5fdc57a 6a10 push 10h fffff802`c5fdc57c 488d05fd5e0000 lea rax,[nt!KiServiceLinkage (fffff802`c5fe2480)] fffff802`c5fdc583 50 push rax fffff802`c5fdc584 b836000000 mov eax,36h fffff802`c5fdc589 e9b2d30000 jmp nt!KiServiceInternal (fffff802`c5fe9940) Branch nt!KiServiceInternal: fffff802`c5fe9940 4883ec08 sub rsp,8 fffff802`c5fe9944 55 push rbp fffff802`c5fe9945 4881ec58010000 sub rsp,158h fffff802`c5fe994c 488dac2480000000 lea rbp,[rsp+80h] fffff802`c5fe9954 48899dc0000000 mov qword ptr [rbp+0C0h],rbx fffff802`c5fe995b 4889bdc8000000 mov qword ptr [rbp+0C8h],rdi fffff802`c5fe9962 4889b5d0000000 mov qword ptr [rbp+0D0h],rsi fffff802`c5fe9969 fb sti fffff802`c5fe996a 65488b1c2588010000 mov rbx,qword ptr gs:[188h] fffff802`c5fe9973 0f0d8b90000000 prefetchw [rbx+90h] fffff802`c5fe997a 0fb6bb32020000 movzx edi,byte ptr [rbx+232h] fffff802`c5fe9981 40887da8 mov byte ptr [rbp-58h],dil fffff802`c5fe9985 c6833202000000 mov byte ptr [rbx+232h],0 fffff802`c5fe998c 4c8b9390000000 mov r10,qword ptr [rbx+90h] fffff802`c5fe9993 4c8995b8000000 mov qword ptr [rbp+0B8h],r10 fffff802`c5fe999a 4c8d1d4f010000 lea r11,[nt!KiSystemServiceStart (fffff802`c5fe9af0)] fffff802`c5fe99a1 41ffe3 jmp r11 0: kd> dq KeServiceDescriptorTable fffff802`c6254740 fffff802`c6197020 00000000`00000000 fffff802`c6254750 00000000`000001b9 fffff802`c6197dec fffff802`c6254760 00000000`00000000 00000000`00000000 fffff802`c6254770 00000000`00000000 00000000`00000000 fffff802`c6254780 00000000`00000000 00000000`00000000 fffff802`c6254790 00000000`009c19c2 00007ffb`8c4c56f0 fffff802`c62547a0 ffffe001`f0574360 ffffe001`f0576b00 fffff802`c62547b0 00000000`00000000 00000000`00000000 0: kd> dd fffff802`c6197020+d8h fffff802`c61970f8 01040800 02118100 03df6e41 0185b146 fffff802`c6197108 02264f81 021a66c0 01450003 020cf900 fffff802`c6197118 0208d000 0128e601 0216e140 019f3a02 fffff802`c6197128 014d02c2 fe48c500 02460600 021eb2c1 fffff802`c6197138 fd030300 03e74980 0102c301 01d6c501 fffff802`c6197148 01409e03 02247680 01ef4780 02355305 fffff802`c6197158 03aeda84 016b01c0 010ceb01 021fdd81 fffff802`c6197168 012f6580 012e8240 038ee042 017aa207 0: kd> u fffff802`c6197020+0104080 nt!NtQuerySystemInformation: fffff802`c629b0a0 4883ec38 sub rsp,38h fffff802`c629b0a4 458bd0 mov r10d,r8d fffff802`c629b0a7 4c8bda mov r11,rdx fffff802`c629b0aa 83f94a cmp ecx,4Ah fffff802`c629b0ad 7c21 jl nt!NtQuerySystemInformation+0x30 (fffff802`c629b0d0) fffff802`c629b0af 83f953 cmp ecx,53h fffff802`c629b0b2 7d1c jge nt!NtQuerySystemInformation+0x30 (fffff802`c629b0d0) fffff802`c629b0b4 33d2 xor edx,edx 0: kd> ed fffff802`c61970f8 02118100 0: kd> dd fffff802`c61970f8 fffff802`c61970f8 02118100 02118100 03df6e41 0185b146 fffff802`c6197108 02264f81 021a66c0 01450003 020cf900 fffff802`c6197118 0208d000 0128e601 0216e140 019f3a02 fffff802`c6197128 014d02c2 fe48c500 02460600 021eb2c1 fffff802`c6197138 fd030300 03e74980 0102c301 01d6c501 fffff802`c6197148 01409e03 02247680 01ef4780 02355305 fffff802`c6197158 03aeda84 016b01c0 010ceb01 021fdd81 fffff802`c6197168 012f6580 012e8240 038ee042 017aa207 0: kd> g
開調試能夠關patch guard,由於int3會修改內核,若是pg還發揮做用就會藍屏,無法調試了,因此調試便可關pg。bat代碼以下:前端
Bcdedit /debug ON Bcdedit /dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200 /start AUTOENABLE /noumex
如下是轉載:windows
一、利用NEWBLUEPILL進入VT建立 HYPERVISOR
二、對你但願關心的系統服務函數下硬件斷點
三、HYPERVISOR捕獲到INT1異常之後你就能夠判斷是否放行 或者不放行了
四、HYPERVISOR處理完之後vmresume之後必定要記得清除RFLAG單步標誌位
五、HYPERVISOR注意不要向操做系統注入INT1異常 且HYPERVISOR必定要拒絕其餘代碼修改DR調試寄存器數組
hook技術分爲兩塊:bash
Ring3層的hook又分爲兩種類型函數
以下圖所示:工具
hook1測試
hook2fetch
hook1spa
關於Windows消息的Hook,相信不少朋友都有接觸過的,由於一個SetWindowsHookEx便可以完成消息 Hook,在這裏簡要介紹一下消息 Hook,消息 Hook 是經過SetWindowsHookEx能夠實現將本身的鉤子插入到鉤子鏈的最前端,而對於發送給被 Hook 的窗口(也有多是全部的窗口,即全局 Hook)的消息都會被咱們的鉤子處理函數所捕獲到,也就是咱們能夠優先於窗體先捕獲到這些消息,Windows 消息 Hook 能夠實現爲進程內消息 Hook 和全局消息 Hook,對於進程內消息 Hook,則能夠簡單的將 Hook 處理函數直接寫在這個進程內,便是本身 Hook 本身,而對於用途更爲普遍的全局消息 Hook,則須要將 Hook 處理函數寫在一個 DLL 中,這樣纔可讓你的處理函數被全部的進程所加載(進程自動加載包含 Hook 消息處理函數的 DLL)。
對於 Windows 消息 Hook 呢,能夠有個簡單的邪惡應用,就是記錄鍵盤按鍵消息,從而達到監視用戶輸入的鍵值信息的目的,這樣,對於一些簡單的用戶經過鍵盤輸入的密碼就能夠被 Hook 獲取到,由於沒當用戶按下一個鍵時,Windows 都會產生一個按鍵消息(固然有按下,彈起等消息的區分),而後咱們能夠 Hook 到這個按鍵消息,這樣就能夠在 Hook 的消息處理函數中獲取到用戶按下的是什麼鍵了。
不過消息的hook不是本文的重點。
本文要講的SSDT hook呢實際上是屬於內核Hook,常見於病毒以及殺軟中。
下圖展現了內核hook的幾個基本類型。
Kernel hook
SSDT全稱System Service Descriptor Table(系統描述符表),這個表用於將Ring3的Win32API和內核的API聯繫起來。
SSDT並不只僅只包含一個龐大的地址索引表,它還包含一些有用的信息,如地址索引的基地址,服務函數的個數等。經過修改此表能夠達到對一些關心的系統動做進行過濾以及監控的目的。
在NT4.0的windows操做系統中,默認存在兩個系統服務描述符表,這兩個描述符表對應了兩類不一樣的系統服務,這兩個表爲:KeServiceDescriptorTable(SSDT)和KeServiceDescriptorTable(SSDT Shadow)。其中SSDT負責處理來自Ring3層的Kernel32.dll的系統調用。而SSDT Shadow則主要處理來自User32.dll和GDI32.dll的系統調用。同時SSDT在ntoskrnl.exe中是導出的,而SSDT Shadow如其名是未被Windows所導出的,而關於SSDT的所有內容都是通KeServiceDescriptorTable來完成的。
如下截圖說明,KeServiceDescriptorTable是在ntoskrnl.exe中被導出的:
Export1
隨後咱們看看看看Windows操做系統的源碼中如何定義KeServiceDescriptorTable的,經過觀察WRK可知,
KeServiceDescriptorTable in WRK
這麼看仍是有點蛋疼啊。改寫如下變量的名稱吧。
typedef struct _KSYSTEM_SERVICE_TABLE{ PULONG ServiceTableBase; //SSDT的基地址指針 PULONG ServiceCounterTableBase; //SSDT中每一個服務被調用次數表的基地址指針 ULONG NumberOfService; //服務函數個數,NumberOfService*4就是整個地址表的大小 ULONG ParamTableBase; //SSPT的基地址 }KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE; typedef struct _KSERVICE_TABLE_DESCRIPTOR{ KSYSTEM_SERVICE_TABLE ntoskrnl; //ntoskrnl.exe的服務函數 KSYSTEM_SERVICE_TABLE win32k; //win32k.sys的服務函數(GDI32/User32) KSYSTEM_SERVICE_TABLE notUsed1; KSYSTEM_SERVICE_TABLE notUsed2; }KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR; //導出由ntoskrnl.exe所導出的SSDT extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
從上述介紹可知,KeServiceDescriptorTable能夠看作是一個數組,是4個KSYSTEM_SERVICE_TABLE結構造成的數組,而每一個KSYSTEM_SERVICE_TABLE對應一個PE文件導出的服務描述符表,根據這些服務描述符表咱們能夠得到更加詳細的服務信息。在應用層ntdll.dll中的API在這個系統服務描述表中都存在一個與之對應的服務,當咱們的應用程序調用ntdll.dll裏的API時最終能夠調用對應的系統服務函數,通知給內核一個索引,內核經過該索引在SSDT中查找對應的服務,內核調用服務完成應用的API調用請求。
有了以上的SSDT基礎後,咱們再來看看在應用層調用Win32API(主要指ntdll.dll中的API)的流程,咱們主要針對ntdll.dll中的NtQuerySystemInformation這個API的調用流程來進行闡述。
這裏存在四個相似的API。
4APIs
再給出這些API的調用流程。
calling way
這裏咱們能夠看到ntdll.dll中的nt和zw都會進入內核層去調用ntoskrnl的zw函數,而zw最終會調用nt函數,這個函數做爲內核API最終去請求系統服務的執行。
用exescope工具能夠打開ntdll.dll,看到NtQuerySystemInformation以及ZwQuerySystemInformation。
ntdll1
ntdll2
而實質上zw和nt都是同一函數,指向同一區域,入口地址相同。
所以Ntdll.dll中的API都是對內核API的封裝,當Kernel32.dll中的API經過Ntdll.dll去調用系統API時,會進行參數檢查,並調用中斷(int 2Eh或SysEnter),從而從Ring3進入Ring0,並將所要調用的服務號,即SSDT數組的索引值,存放進寄存器EAX中,而且將參數地址放到指定的寄存器EDX中,再複製參數到內核地址空間,根據存放在EAX中的索引值來在SSDT數組中調用指定的服務。
通過上面步驟咱們來到Ring0層。使用exescope看看ntoskrnl.exe中的ZwQuerySystemInformation以及NtQuerySystemInformation。
ntoskrnl1
ntoskrnl2
再反彙編ntoskrnl這個文件能夠看到Zw函數中調用KiSystemService系統服務分發函數時往EAX中存放了索引號ADh。如圖:
ZwQSystemInfor
隨後根據該索引值檢索SSDT項,最後根據該SSDT項中所存放的系統服務地址來調用這個系統服務。在這裏就是調用KeServiceDescriptorTable[ADh]處保存的地址對應的系統服務。那就是Ring0下的NtQuerySystemInformation。
這節內咱們用WinDbg來調試XP系統,藉此說明SSDT是個什麼鬼。
據咱們上文的結構定義可知,KeServiceDescriptorTable是一個指向4個KSYSTEM_SERVICE_TABLE結構首地址的指針,如下圖爲例吧。
dd KeServiceDescriptorTable
這裏的0x80563520這一行就是ntoskrnl對應的服務描述符表結構KSYSTEM_SERVICE_TABLE。那麼第一個32位的0x804e58a0則是對應ntoskrnl對應的KSYSTEM_SERVICE_TABLE中的SSDT Base,即服務描述符表的首地址。經過對該首地址的dump,咱們能夠看到許多以128位爲一組排列的服務描述符,每一個描述符中的第一個32位(0x80591bfb)對應着系統服務的入口地址。經過對該入口地址的反彙編,能夠看到這是SSDT第一個系統服務NtAcceptConnectPort函數。如圖:
NtAcceptConnectPort
那麼知道了SSDT首地址,同時知道了索引,那麼咱們就能夠經過索引來找到對應的系統服務入口地址了。經過計算「SSDT中系統服務地址所在的地址 = SSDT首地址 + 4 * 索引值」,能夠推算出NtQuerySystemInformation的起始地址位0x80586ff1,對該地址進行反彙編,可得下圖:
NtQuerySystemInformation
由此可知,SSDT就是個保存Windows系統服務地址的數組。
從上面的分析中咱們能夠看到SSDT數組中保存了系統服務的地址,如Ring0下的NtQuerySystemInformation系統服務地址,就保存在KeServiceDescriptorTable[ADh]中,既然hook就是取出這個地址後替換上咱們的hook函數,在hook函數中執行原函數便可。
參考文獻:
http://www.cnblogs.com/boyxiao/archive/2011/09/03/2164574.html
轉載的原文地址:
https://www.jianshu.com/p/28af7d0b592f