Sysenter/Kifastcallentry hook 检测与恢复
阅读原文时间:2023年07月12日阅读:1

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

}