关于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); }