關於Sysenter、Kifastcallentry、中斷之類的內核入口hook技術早就爛大街了,可是對hook的檢測與恢復代碼卻是寥寥無幾,一切拋開代碼將原理的行為都是耍流氓。
下面以Sysenter hook技術為例子,重點分析下這類鈎子的檢測與恢復技術。
Sysenter簡述 :
Windows2000以前用int 2e作為中斷指令進入內核發起系統調用。從Windows2000以后,准確的說是Pentium II處理器開始,為了避免int 2e指令對模式切換的巨大開銷,Intel引入了一對新的指令,sysenter/sysexit,實現快速的模式切換,所以也叫快速系統調用。 關於兩者之間的具體異同請參考潘愛民老師《Windows內核原理與實現》第8章Windows系統服務,再次不是分析重點,不在累贅。
sysenter使用三個MSR(Model Specific Register)寄存器來指定跳轉目標地址和棧位置。操作系統在內核模式下通過rdmsr/wrmsr特權指令來設置這三個寄存器,當然必須在系統初始化時(第一次系統調用發生以前)完成。
MSR寄存器 MSR地址 含義
IA32_SYSENTRY_CS 174h 低16位值制訂了特權級0的代碼段和棧段的段選擇符
IA32_SYSENTRY_ESP 175h 內核棧指針的32位偏移
IA32_SYSENTRY_EIP 176h 目標例程的32位偏移(Kifastcallentry地址)
根據這三個MSR寄存器的屬性我們看一段代碼
_asm { mov ecx,0x176 rdmsr mov KifastcalllAddress,eax }
獲取Kifastcallentry地址其實只需要三行匯編就可以搞定,但是有很多人說看不懂。
RDMSR將64位由ECX寄存器指定的MSR(model specific register,模式指定寄存器)的內容讀出至寄存器EDX:EAX中(在支持intel64架構的處理器中RCX的高32位忽略)。MSR的高32位內容存放在EDX寄存器中,MSR的低32位內容存放在EAX寄存器(在支持intel64架構的處理器中RDX和RAX的高32位忽略)。
說這么多其實就是把MSR寄存器地址放進ECX,然后通過RDMSR特權指令就能把相應MSR寄存器的值讀進EAX中。而IA32_SYSENTRY_EIP寄存器中保存的就是Kifastcallentry地址。
Sysenter hook:
下面看一個替換IA32_SYSENTRY_EIP值進行sysentry hook小Demo。
#include "HookSysenter.h" ULONG OriginalAddress = 0; ULONG i = 0; __declspec(naked)FakeAddress() { _asm { mov i,eax } __asm { pushad push fs push 0x30 pop fs } if (i==0x101) { DbgPrint("Terminate\r\n"); } _asm { pop fs popad jmp [OriginalAddress] } } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath) { DriverObject->DriverUnload = UnloadDriver; DbgPrint("Hello\r\n"); Hook(); return STATUS_SUCCESS; } VOID UnloadDriver(PDRIVER_OBJECT DriverObject) { UnHook(); } VOID Hook() { _asm { mov ecx,0x176 rdmsr mov OriginalAddress,eax mov eax, FakeAddress wrmsr } } VOID UnHook() { KIRQL oldIrql; oldIrql=KeRaiseIrqlToDpcLevel(); _asm { mov ecx,0x176 mov eax,OriginalAddress wrmsr } KeLowerIrql(oldIrql); }
只是替換Kifastcallentry地址,然后簡單判斷了下是否發起對NTterminateProcess的系統調用,很簡單。
那么問題來了,我們如何通過內核文件去尋找原始的Kifastcallentry呢?
內核Ntoskrnl.exe的OEP入口函數可以理解是kisystemstartup,然后我們用WinDbg來看一看這個函數。
kd> u kisystemstartup nt!KiSystemStartup: 806907e0 0000 add byte ptr [eax],al 806907e2 0000 add byte ptr [eax],al 806907e4 0000 add byte ptr [eax],al 806907e6 0000 add byte ptr [eax],al 806907e8 0000 add byte ptr [eax],al 806907ea 0000 add byte ptr [eax],al 806907ec 0000 add byte ptr [eax],al 806907ee 0000 add byte ptr [eax],al
竟然什么都沒有! 原來操作系統啟動后默認為這一函數就失去了價值就把相關的內存釋放了,我們自然什么都看不到,那么我們如何獲得這個函數的真正信息呢? 在操作系統啟動前WinDbg攔截就可以了。

kd> u kisystemstartup l 100 nt!KiSystemStartup: 806907e0 55 push ebp 806907e1 8bec mov ebp,esp 806907e3 83ec20 sub esp,20h 806907e6 8b5d08 mov ebx,dword ptr [ebp+8] 806907e9 891ddcd45480 mov dword ptr [nt!KeLoaderBlock (8054d4dc)],ebx 806907ef 0fb60de0d45480 movzx ecx,byte ptr [nt!KeNumberProcessors (8054d4e0)] 806907f6 894de8 mov dword ptr [ebp-18h],ecx 806907f9 0bc9 or ecx,ecx 806907fb 7519 jne nt!KiSystemStartup+0x36 (80690816) 806907fd c7432440375580 mov dword ptr [ebx+24h],offset nt!KiIdleThread0 (80553740) 80690804 c7431800af5480 mov dword ptr [ebx+18h],offset nt!P0BootStack (8054af00) 8069080b 6a30 push 30h 8069080d 0fa1 pop fs 8069080f 64880d30010000 mov byte ptr fs:[130h],cl 80690816 8b4324 mov eax,dword ptr [ebx+24h] 80690819 8945e0 mov dword ptr [ebp-20h],eax 8069081c 8b4318 mov eax,dword ptr [ebx+18h] 8069081f 8945e4 mov dword ptr [ebp-1Ch],eax 80690822 e8d10b0000 call nt!KiInitializeMachineType (806913f8) 80690827 807de800 cmp byte ptr [ebp-18h],0 8069082b 0f859f010000 jne nt!KiSystemStartup+0x1f0 (806909d0) 80690831 e8b216ebff call nt!GetMachineBootPointers (80541ee8) 80690836 897dfc mov dword ptr [ebp-4],edi 80690839 8975f8 mov dword ptr [ebp-8],esi 8069083c 8955f4 mov dword ptr [ebp-0Ch],edx 8069083f 8945f0 mov dword ptr [ebp-10h],eax 80690842 8d4f28 lea ecx,[edi+28h] 80690845 c6410589 mov byte ptr [ecx+5],89h 80690849 51 push ecx 8069084a ff75f4 push dword ptr [ebp-0Ch] 8069084d e81c110000 call nt!KiInitializeTSS2 (8069196e) 80690852 ff75f4 push dword ptr [ebp-0Ch] 80690855 e872fbe6ff call nt!KiInitializeTSS (805003cc) 8069085a 66b92800 mov cx,28h 8069085e 0f00d9 ltr cx 80690861 8b45f0 mov eax,dword ptr [ebp-10h] 80690864 8d4840 lea ecx,[eax+40h] 80690867 c6410585 mov byte ptr [ecx+5],85h 8069086b 66c741025000 mov word ptr [ecx+2],50h 80690871 8d4f50 lea ecx,[edi+50h] 80690874 c6410589 mov byte ptr [ecx+5],89h 80690878 ba00af5480 mov edx,offset nt!P0BootStack (8054af00) 8069087d 8bc2 mov eax,edx 8069087f 66894102 mov word ptr [ecx+2],ax 80690883 c1e810 shr eax,10h 80690886 886107 mov byte ptr [ecx+7],ah 80690889 884104 mov byte ptr [ecx+4],al 8069088c b868000000 mov eax,68h 80690891 668901 mov word ptr [ecx],ax 80690894 52 push edx 80690895 e832fbe6ff call nt!KiInitializeTSS (805003cc) 8069089a 0f20d8 mov eax,cr3 8069089d 89421c mov dword ptr [edx+1Ch],eax 806908a0 b8007f5480 mov eax,offset nt!KiDoubleFaultStack (80547f00) 806908a5 894238 mov dword ptr [edx+38h],eax 806908a8 894204 mov dword ptr [edx+4],eax 806908ab c74220ce045480 mov dword ptr [edx+20h],offset nt!KiTrap08 (805404ce) 806908b2 c7422400000000 mov dword ptr [edx+24h],0 806908b9 66c7424c0800 mov word ptr [edx+4Ch],8 806908bf 66c742583000 mov word ptr [edx+58h],30h 806908c5 8c5250 mov word ptr [edx+50h],ss 806908c8 66c742482300 mov word ptr [edx+48h],23h 806908ce 66c742542300 mov word ptr [edx+54h],23h 806908d4 8b45f0 mov eax,dword ptr [ebp-10h] 806908d7 8d4810 lea ecx,[eax+10h] 806908da c6410585 mov byte ptr [ecx+5],85h 806908de 66c741025800 mov word ptr [ecx+2],58h 806908e4 8d4f58 lea ecx,[edi+58h] 806908e7 c6410589 mov byte ptr [ecx+5],89h 806908eb ba68af5480 mov edx,offset nt!KiNMITSS (8054af68) 806908f0 8bc2 mov eax,edx 806908f2 66894102 mov word ptr [ecx+2],ax 806908f6 c1e810 shr eax,10h 806908f9 886107 mov byte ptr [ecx+7],ah 806908fc 884104 mov byte ptr [ecx+4],al 806908ff b868000000 mov eax,68h 80690904 668901 mov word ptr [ecx],ax 80690907 52 push edx 80690908 52 push edx 80690909 e8befae6ff call nt!KiInitializeTSS (805003cc) 8069090e 0f20d8 mov eax,cr3 80690911 89421c mov dword ptr [edx+1Ch],eax 80690914 b800af5480 mov eax,offset nt!P0BootStack (8054af00) 80690919 8b4038 mov eax,dword ptr [eax+38h] 8069091c 894204 mov dword ptr [edx+4],eax 8069091f 894238 mov dword ptr [edx+38h],eax 80690922 c74220fcf35380 mov dword ptr [edx+20h],offset nt!KiTrap02 (8053f3fc) 80690929 c7422400000000 mov dword ptr [edx+24h],0 80690930 66c7424c0800 mov word ptr [edx+4Ch],8 80690936 66c742583000 mov word ptr [edx+58h],30h 8069093c 8c5250 mov word ptr [edx+50h],ss 8069093f 66c742482300 mov word ptr [edx+48h],23h 80690945 66c742542300 mov word ptr [edx+54h],23h 8069094b 68007f5480 push offset nt!KiDoubleFaultStack (80547f00) 80690950 ff75e0 push dword ptr [ebp-20h] 80690953 ff75f4 push dword ptr [ebp-0Ch] 80690956 ff75fc push dword ptr [ebp-4] 80690959 ff75f0 push dword ptr [ebp-10h] 8069095c ff75f8 push dword ptr [ebp-8] 8069095f ff75e8 push dword ptr [ebp-18h] 80690962 e8630f0000 call nt!KiInitializePcr (806918ca) 80690967 8b55e0 mov edx,dword ptr [ebp-20h] 8069096a b9a0395580 mov ecx,offset nt!KiIdleProcess (805539a0) 8069096f 894a44 mov dword ptr [edx+44h],ecx 80690972 64c7051800000000000000 mov dword ptr fs:[18h],0 8069097d 64c7052804000000000000 mov dword ptr fs:[428h],0 80690988 64c7052c04000000000000 mov dword ptr fs:[42Ch],0 80690993 e83a100000 call nt!KiSwapIDT (806919d2) 80690998 b823000000 mov eax,23h 8069099d 668ed8 mov ds,ax 806909a0 668ec0 mov es,ax 806909a3 8b45f0 mov eax,dword ptr [ebp-10h] 806909a6 ff7040 push dword ptr [eax+40h] 806909a9 ff7044 push dword ptr [eax+44h] 806909ac ff7010 push dword ptr [eax+10h] 806909af ff7014 push dword ptr [eax+14h] 806909b2 8b7df0 mov edi,dword ptr [ebp-10h] 806909b5 befc0a6980 mov esi,offset nt!IDT (80690afc) 806909ba b900080000 mov ecx,800h 806909bf c1e902 shr ecx,2 806909c2 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] 806909c4 8f4014 pop dword ptr [eax+14h] 806909c7 8f4010 pop dword ptr [eax+10h] 806909ca 8f4044 pop dword ptr [eax+44h] 806909cd 8f4040 pop dword ptr [eax+40h] 806909d0 f70558bd548001000000 test dword ptr [nt!KiFreezeExecutionLock (8054bd58)],1 806909da 75f4 jne nt!KiSystemStartup+0x1f0 (806909d0) 806909dc f00fba2d58bd548000 lock bts dword ptr [nt!KiFreezeExecutionLock (8054bd58)],0 806909e5 72e9 jb nt!KiSystemStartup+0x1f0 (806909d0) 806909e7 8b4de8 mov ecx,dword ptr [ebp-18h] 806909ea 64880d51000000 mov byte ptr fs:[51h],cl 806909f1 b801000000 mov eax,1 806909f6 d3e0 shl eax,cl 806909f8 64a348000000 mov dword ptr fs:[00000048h],eax 806909fe 64a334010000 mov dword ptr fs:[00000134h],eax 80690a04 ff7508 push dword ptr [ebp+8] 80690a07 ff75e8 push dword ptr [ebp-18h] 80690a0a ff1574864d80 call dword ptr [nt!_imp__HalInitializeProcessor (804d8674)] 80690a10 64a148000000 mov eax,dword ptr fs:[00000048h] 80690a16 0905d0d45480 or dword ptr [nt!KeActiveProcessors (8054d4d0)],eax 80690a1c ff75e8 push dword ptr [ebp-18h] 80690a1f e876abe6ff call nt!KiInitializeAbios (804fb59a) 80690a24 fe05e0d45480 inc byte ptr [nt!KeNumberProcessors (8054d4e0)] 80690a2a 33c0 xor eax,eax 80690a2c a358bd5480 mov dword ptr [nt!KiFreezeExecutionLock (8054bd58)],eax 80690a31 807de800 cmp byte ptr [ebp-18h],0 80690a35 751d jne nt!KiSystemStartup+0x274 (80690a54) 80690a37 ff35dcd45480 push dword ptr [nt!KeLoaderBlock (8054d4dc)] 80690a3d 6a00 push 0 80690a3f e87a00fdff call nt!KdInitSystem (80660abe) 80690a44 e8956ee6ff call nt!KdPollBreakIn (804f78de) 80690a49 0ac0 or al,al 80690a4b 7407 je nt!KiSystemStartup+0x274 (80690a54) 80690a4d 6a01 push 1 80690a4f e88481e9ff call nt!DbgBreakPointWithStatus (80528bd8) 80690a54 90 nop 80690a55 b91f000000 mov ecx,1Fh 80690a5a ff15f4864d80 call dword ptr [nt!_imp_KfRaiseIrql (804d86f4)] 80690a60 8845ec mov byte ptr [ebp-14h],al 80690a63 810dcc3c558080000000 or dword ptr [nt!KiBootFeatureBits (80553ccc)],80h 80690a6d 8b5de0 mov ebx,dword ptr [ebp-20h] 80690a70 8b55e4 mov edx,dword ptr [ebp-1Ch] 80690a73 8b45e8 mov eax,dword ptr [ebp-18h] 80690a76 83e2fc and edx,0FFFFFFFCh 80690a79 33ed xor ebp,ebp 80690a7b 8be2 mov esp,edx 80690a7d 81eca0020000 sub esp,2A0h 80690a83 6a0e push 0Eh 80690a85 ff35dcd45480 push dword ptr [nt!KeLoaderBlock (8054d4dc)] 80690a8b 50 push eax 80690a8c 64ff3520000000 push dword ptr fs:[20h] 80690a93 52 push edx 80690a94 53 push ebx 80690a95 68a0395580 push offset nt!KiIdleProcess (805539a0) 80690a9a e8d7200000 call nt!KiInitializeKernel (80692b76) 80690a9f 648b1d24010000 mov ebx,dword ptr fs:[124h] 80690aa6 c6433310 mov byte ptr [ebx+33h],10h 80690aaa fb sti 80690aab b902000000 mov ecx,2 80690ab0 ff151c874d80 call dword ptr [nt!_imp_KfLowerIrql (804d871c)] 80690ab6 c6435802 mov byte ptr [ebx+58h],2 80690aba 8b1d1cf0dfff mov ebx,dword ptr ds:[0FFDFF01Ch] 80690ac0 6a00 push 0 80690ac2 e91920ebff jmp nt!KiIdleLoop (80542ae0) 80690ac7 90 nop
在kisystemstartup函數中我們可以清楚的看到IDT
806909b2 8b7df0 mov edi,dword ptr [ebp-10h] 806909b5 befc0a6980 mov esi,offset nt!IDT (80690afc) 806909ba b900080000 mov ecx,800h 806909bf c1e902 shr ecx,2
我們看一下IDT,此時應該注意在操作系統啟動前,不然我們和kisystemstartup一樣什么都得不到。
kd> dq 80690afc 80690afc 80538e00`0008f19c 80538e00`0008f314 80690b0c 80538e00`0008f3fc 8053ee00`0008f6e4 80690b1c 8053ee00`0008f864 80538e00`0008f9c0 80690b2c 80538e00`0008fb34 80548e00`0008019c 80690b3c 80548e00`000804ce 80548e00`000805c0 80690b4c 80548e00`000806e0 80548e00`00080820 80690b5c 80548e00`00080a7c 80548e00`00080d60 80690b6c 80548e00`00081450 80548e00`00081780
到此已經通過這些獲得Ntoskrnl.exe文件中IDT地址,那么寫出恢復IDT HOOK的代碼了,但是我們要尋找的是Kifastcallentry地址。所以我們繼續看看。
kd> u kitrap01 l 50 nt!KiTrap01: 8053f314 6a00 push 0 8053f316 66c74424020000 mov word ptr [esp+2],0 8053f31d 55 push ebp 8053f31e 53 push ebx 8053f31f 56 push esi 8053f320 57 push edi 8053f321 0fa0 push fs 8053f323 bb30000000 mov ebx,30h 8053f328 668ee3 mov fs,bx 8053f32b 648b1d00000000 mov ebx,dword ptr fs:[0] 8053f332 53 push ebx 8053f333 83ec04 sub esp,4 8053f336 50 push eax 8053f337 51 push ecx 8053f338 52 push edx 8053f339 1e push ds 8053f33a 06 push es 8053f33b 0fa8 push gs 8053f33d 66b82300 mov ax,23h 8053f341 83ec30 sub esp,30h 8053f344 668ed8 mov ds,ax 8053f347 668ec0 mov es,ax 8053f34a 8bec mov ebp,esp 8053f34c f744247000000200 test dword ptr [esp+70h],20000h 8053f354 7596 jne nt!V86_kit1_a (8053f2ec) 8053f356 fc cld 8053f357 8b5d60 mov ebx,dword ptr [ebp+60h] 8053f35a 8b7d68 mov edi,dword ptr [ebp+68h] 8053f35d 89550c mov dword ptr [ebp+0Ch],edx 8053f360 c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h 8053f367 895d00 mov dword ptr [ebp],ebx 8053f36a 897d04 mov dword ptr [ebp+4],edi 8053f36d f60550f0dfffff test byte ptr ds:[0FFDFF050h],0FFh 8053f374 0f85eefeffff jne nt!Dr_kit1_a (8053f268) 8053f37a 833d54f0dfff00 cmp dword ptr ds:[0FFDFF054h],0 8053f381 7560 jne nt!KiTrap01+0xcf (8053f3e3) 8053f383 8b4d68 mov ecx,dword ptr [ebp+68h] 8053f386 81f940e55380 cmp ecx,offset nt!KiFastCallEntry (8053e540) 8053f38c 0f84c6feffff je nt!KiTrap00+0xbc (8053f258) 8053f392 f7457000000200 test dword ptr [ebp+70h],20000h 8053f399 7524 jne nt!KiTrap01+0xab (8053f3bf) 8053f39b 66f7456c0100 test word ptr [ebp+6Ch],1 8053f3a1 7408 je nt!KiTrap01+0x97 (8053f3ab) 8053f3a3 66837d6c1b cmp word ptr [ebp+6Ch],1Bh 8053f3a8 7515 jne nt!KiTrap01+0xab (8053f3bf) 8053f3aa fb sti 8053f3ab 816570fffeffff and dword ptr [ebp+70h],0FFFFFEFFh 8053f3b2 8b5d68 mov ebx,dword ptr [ebp+68h] 8053f3b5 b804000080 mov eax,80000004h 8053f3ba e954fcffff jmp nt!KiExceptionExit+0x16b (8053f013) 8053f3bf 8b1d24f1dfff mov ebx,dword ptr ds:[0FFDFF124h] 8053f3c5 8b5b44 mov ebx,dword ptr [ebx+44h] 8053f3c8 83bb5801000000 cmp dword ptr [ebx+158h],0 8053f3cf 74d9 je nt!KiTrap01+0x96 (8053f3aa) 8053f3d1 6a01 push 1 8053f3d3 e8b42a0000 call nt!Ki386VdmReflectException_A (80541e8c) 8053f3d8 66a9ffff test ax,0FFFFh 8053f3dc 74cd je nt!KiTrap01+0x97 (8053f3ab) 8053f3de e9c5faffff jmp nt!Kei386EoiHelper (8053eea8) 8053f3e3 a154f0dfff mov eax,dword ptr ds:[FFDFF054h] 8053f3e8 c70554f0dfff00000000 mov dword ptr ds:[0FFDFF054h],0 8053f3f2 894568 mov dword ptr [ebp+68h],eax 8053f3f5 8be5 mov esp,ebp 8053f3f7 e9acfaffff jmp nt!Kei386EoiHelper (8053eea8)
我們在IDT的KiTrap01 處理調試異常(Debug Exception)的例程可以看到Kifastcallentry的地址,那么我們就可以用它來進行恢復Sysentry hook以及Kifastcallentry hook了。
下面我們來看看完成代碼。
#include "CheckKiFastCall.h" #include "Asm.H" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { CheckKiFastCallHook(TRUE); DriverObject->DriverUnload = UnloadDriver; return STATUS_SUCCESS; } VOID UnloadDriver(PDRIVER_OBJECT DriverObject) { } int CheckKiFastCallHook(BOOLEAN UnHook) { MODULE_INFO KernelModule; PULONG KernelBaseAddress = NULL; PIMAGE_NT_HEADERS Ntheader = NULL; PUCHAR EntryPointer = NULL; //OEP int Strlen = 0; PRAW_IDT rawIDT = NULL; ULONG IDTBaseAddr = 0; ULONG ImageBase = 0; int Diff = 0; PULONG Temp = NULL; ULONG Address = 0; ULONG KiFmAddr = 0; KIRQL Irq; if (GetKernelBase(&KernelModule)==0) { DbgPrint("Get ntkrnlpa.exe Error\r\n"); return -1; } KernelBaseAddress = (PVOID)MapViewOfImage(KernelModule.FullPath); if(!KernelBaseAddress) { return -1; } Ntheader = (PIMAGE_NT_HEADERS)((ULONG)KernelBaseAddress+((PIMAGE_DOS_HEADER)(KernelBaseAddress))->e_lfanew); EntryPointer = (PUCHAR)((ULONG)KernelBaseAddress+Ntheader->OptionalHeader.AddressOfEntryPoint); //獲得代碼的入口OEP DbgPrint("OEP:%x\r\n",EntryPointer); while (1) { PUCHAR Code = 0; Strlen = SizeOfCode((VOID*)EntryPointer,&Code); if (Strlen<=0) //沒有獲得指令 { break; } if (*Code==0xc2) { break; } if (*Code==0xc3) { break; } //以上兩條Opcode都是return 可以使用查看Demo if (Strlen==5) { rawIDT = (PRAW_IDT)EntryPointer; DbgPrint("%x %x %x\r\n",rawIDT->d_800h,rawIDT->Opcode1,rawIDT->Opcode2); if((rawIDT->d_800h==0x800)&&(rawIDT->Opcode1==0xbe)&&(rawIDT->Opcode2==0xb9)) { IDTBaseAddr = rawIDT->OrigBase; //DbgPrint("%x\r\n",IDTBaseAddr); break; } } EntryPointer+=Strlen; } if (IDTBaseAddr==0) { ZwUnmapViewOfSection((HANDLE)-1,(PVOID)KernelBaseAddress); return -1; } ImageBase = GetImageBase(KernelBaseAddress); Diff = (ULONG)KernelBaseAddress - (ULONG)ImageBase; IDTBaseAddr += Diff; Temp = (PULONG)IDTBaseAddr; Temp+=2; Address = *(Temp)+Diff; DbgPrint("%x\r\n",Address); Address = GetKiFastCallEntryOrigEntry((PUCHAR)Address); if (Address==0) { ZwUnmapViewOfSection((HANDLE)-1,(PVOID)KernelBaseAddress); return -1; } _asm { mov ecx,0x176 rdmsr mov KiFmAddr,eax } if((Address+(ULONG)KernelModule.Base-ImageBase)!=KiFmAddr) { DbgPrint("KiFastCallEntry Hooked!\n"); KdPrint(("KiFastCallEntry Current Addr :%08X Orig Address:%08X\n",KiFmAddr,Address+(ULONG)KernelModule.Base-ImageBase)); if(UnHook) { Irq=WPOFF(); HookKiFastCallEntry(Address+(ULONG)KernelModule.Base-ImageBase); WPON(Irq); } } ZwUnmapViewOfSection((HANDLE)-1,(PVOID)KernelBaseAddress); return 1; } ULONG GetKernelBase(PMODULE_INFO OutInfo) { NTSTATUS Status = STATUS_UNSUCCESSFUL; ULONG Base = 0; ULONG BufferSize = 0x3000; PVOID Buffer = NULL; char NameBuffer[256] = {0}; __try { Buffer= ExAllocatePool(PagedPool,BufferSize); if(Buffer==0) { return 0; } NtQuerySystemInformation(SystemModuleInformation,Buffer,BufferSize,&Base); Base = 0; if(*(ULONG*)Buffer>0) { PSYSTEM_MODULE_INFORMATION_ENTRY pInfo= (PSYSTEM_MODULE_INFORMATION_ENTRY)((char*)Buffer+sizeof(ULONG)); Base = (ULONG)pInfo[0].Base; if(OutInfo) { OutInfo->Base=pInfo[0].Base; OutInfo->ImageSize=pInfo[0].Size;//ImageSize; DbgPrint("%x\r\n",OutInfo->Base); DbgPrint("%d\r\n",OutInfo->ImageSize); DbgPrint("%s\r\n",pInfo[0].ImageName); ConvertFileName(pInfo[0].ImageName,NameBuffer); //查看注冊表 Regedit ByteToWChar(NameBuffer,OutInfo->FullPath,256*2); } } if(Buffer!=NULL) { ExFreePool(Buffer); } return Base; } __except(1) { DbgPrint("Can't Get KernelBase!\r\n"); return 0; } } VOID ConvertFileName(CHAR *ImageName, CHAR* FileName) { int Pos = strlen(ImageName)-1; for(;Pos>0;Pos--) { if(ImageName[Pos]=='\\') { Pos++; break; } } if (ImageName[0]=='\\'&&(_strnicmp(ImageName, "\\windows\\system32\\", 18)==0)) { strcpy(FileName, "\\SystemRoot\\System32\\"); strcat(FileName,ImageName + Pos); } } PULONG MapViewOfImage(PWCHAR ImagePath) { HANDLE hFile = NULL; HANDLE hSection = NULL; OBJECT_ATTRIBUTES oa = {0}; UNICODE_STRING FileName; IO_STATUS_BLOCK iosb; NTSTATUS Status; PULONG BaseAddress = NULL; ULONG Size = 0; RtlInitUnicodeString(&FileName,ImagePath); InitializeObjectAttributes(&oa,&FileName,OBJ_CASE_INSENSITIVE |OBJ_KERNEL_HANDLE,NULL,NULL); Status = ZwCreateFile(&hFile,GENERIC_READ,&oa,&iosb,0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_OPEN,FILE_SYNCHRONOUS_IO_NONALERT, 0,0); if(!NT_SUCCESS(Status)) { return NULL; } if(hFile==NULL) { DbgPrint("ZwCreateFile() Failed!\r\n"); return NULL; } oa.ObjectName = 0; Status = ZwCreateSection(&hSection,SECTION_MAP_READ,&oa,0,PAGE_READONLY,SEC_IMAGE,hFile); if(!NT_SUCCESS(Status)) { DbgPrint("ZwCreateSection() Failed!\r\n"); ZwClose(hFile); return NULL; } Status = ZwMapViewOfSection(hSection, ZwCurrentProcess(),&BaseAddress,0,1000,NULL,&Size,1,MEM_TOP_DOWN,PAGE_READONLY); if(!NT_SUCCESS(Status)) { DbgPrint("ZwMapViewOfSection() Failed!\r\n"); ZwClose(hSection); ZwClose(hFile); } ZwClose(hSection); ZwClose(hFile); DbgPrint("BaseAddress:%x\r\n",BaseAddress); return BaseAddress; } ULONG GetImageBase(PULONG BaseAddr) { PIMAGE_DOS_HEADER DosHeader = NULL; PIMAGE_NT_HEADERS NtHeader = NULL; DosHeader = (PIMAGE_DOS_HEADER)BaseAddr; if (!MmIsAddressValid(DosHeader)) { return 0; } if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } NtHeader = (PIMAGE_NT_HEADERS)((ULONG)DosHeader + DosHeader->e_lfanew); if (!MmIsAddressValid(NtHeader)) { return 0; } if (NtHeader->Signature!=IMAGE_NT_SIGNATURE) { return 0; } return NtHeader->OptionalHeader.ImageBase; } ULONG GetKiFastCallEntryOrigEntry(UCHAR* Address) { int i = 0; UCHAR* Temp = Address; for(i=0;i<1000;i++) { if(*Temp==0x81) //查看Windbg { return *(ULONG*)(Temp+2); } Temp++; } return 0; } BOOLEAN ByteToWChar(char* szSour,wchar_t* szDest,ULONG Size) { if (mbstowcs(szDest,szSour,Size)>0) { return TRUE; } return FALSE; } ULONG HookKiFastCallEntry(ULONG Addr) { ULONG OldAddr; _asm { mov ecx,0x176 rdmsr mov OldAddr,eax mov eax,Addr wrmsr } return OldAddr; } KIRQL WPOFF() { KIRQL OldIrql; KeRaiseIrql(2, &OldIrql); _asm { push eax mov eax, cr0 and eax, 0xFFFEFFFF mov cr0, eax pop eax cli } return OldIrql; } VOID WPON(KIRQL Irq) { _asm { push eax mov eax, cr0 or eax, 0x10000 mov cr0, eax pop eax sti } KeLowerIrql(Irq); }