Sysenter/Kifastcallentry hook 检测与恢复

关于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
View Code

 

在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);
}

 

posted on 2016-04-18 18:13  zbility  阅读(4933)  评论(0编辑  收藏  举报

导航