pjf获得SwapContext地址方法的解析

pjf获得SwapContext地址方法的解析

 

在用hook SwapContext法来检查隐藏进程时,首要条件是获得SwapContext的地址。Pjf在博文 ([1]) 中提出了使用线程KernelStack中保存的地址来获得SwapContext地址的方法。本文主要来解析此法。注意本文中正在运行的、即将被换出的线程我们称为旧线程;即将换进的线程称为新线程。

 

SwapContextKiSwapContext中调用。下面先来看看XPSP2KiSwapContext的汇编代码:

 

nt!KiSwapContext:

8086dbbc 83ec10          sub     esp,10h

8086dbbf 895c240c        mov     dword ptr [esp+0Ch],ebx

8086dbc3 89742408        mov     dword ptr [esp+8],esi

8086dbc7 897c2404        mov     dword ptr [esp+4],edi

8086dbcb 892c24          mov     dword ptr [esp],ebp

8086dbce 648b1d1c000000  mov     ebx,dword ptr fs:[1Ch] <--ebx = kpcr

8086dbd5 8bf1            mov     esi,ecx <--esi=新线程的ETHREAD.

8086dbd7 8bbb24010000    mov     edi,dword ptr [ebx+124h] <--edi=旧线程ETHREAD

8086dbdd 89b324010000    mov     dword ptr [ebx+124h],esi <--当前线程表示已经变了. 

8086dbe3 8a4f58          mov     cl,byte ptr [edi+58h]

 

8086dbe6 e8f5000000      call    nt!SwapContext (8086dce0)

 

8086dbeb 8b2c24          mov     ebp,dword ptr [esp]

8086dbee 8b7c2404        mov     edi,dword ptr [esp+4]

8086dbf2 8b742408        mov     esi,dword ptr [esp+8]

8086dbf6 8b5c240c        mov     ebx,dword ptr [esp+0Ch]

8086dbfa 83c410          add     esp,10h

8086dbfd c3              ret

 

 

再来看看XPSP2SwapContext部分汇编代码:

//ESI为新线程的ETHREADEDI为旧线程的ETHREAD

 nt!SwapContext:

8086dce0 0ac9            or      cl,cl

8086dce2 26c6462d02      mov     byte ptr es:[esi+2Dh],2

8086dce7 9c              pushfd  //<---------旧线程的ESP-4

8086dce8 8d8b40050000    lea     ecx,[ebx+540h]

8086dcee e8ddafffff      call    nt!KeAcquireQueuedSpinLockAtDpcLevel (80868cd0)

8086dcf3 8d8b38050000    lea     ecx,[ebx+538h]

8086dcf9 e8feafffff      call    nt!KeReleaseQueuedSpinLockFromDpcLevel (80868cfc)

8086dcfe 8b0b            mov     ecx,dword ptr [ebx]

8086dd00 83bb9409000000  cmp     dword ptr [ebx+994h],0

8086dd07 51              push    ecx//<---------旧线程的ESP-4

8086dd08 0f8583010000    jne     nt!ScPatchFxe+0x3c (8086de91)

8086dd0e 833d6cc5888000  cmp     dword ptr [nt!PPerfGlobalGroupMask (8088c56c)],0

8086dd15 0f854d010000    jne     nt!ScPatchFxe+0x13 (8086de68)

8086dd1b 0f20c5          mov     ebp,cr0

8086dd1e 8bd5            mov     edx,ebp

8086dd20 807f3100        cmp     byte ptr [edi+31h],0

8086dd24 0f8419010000    je      nt!SwapContext+0x163 (8086de43)

8086dd2a 8a4e2c          mov     cl,byte ptr [esi+2Ch]

8086dd2d 884b50          mov     byte ptr [ebx+50h],cl

8086dd30 fa              cli

8086dd31 896728          mov     dword ptr [edi+28h],esp  //旧线程的ESP保存在KernelStack

 

8086dd34 8b4618          mov     eax,dword ptr [esi+18h]

8086dd37 8b4e1c          mov     ecx,dword ptr [esi+1Ch]

8086dd3a 2d10020000      sub     eax,210h

8086dd3f 894b08          mov     dword ptr [ebx+8],ecx

8086dd42 894304          mov     dword ptr [ebx+4],eax

8086dd45 33c9            xor     ecx,ecx

8086dd47 8a4e31          mov     cl,byte ptr [esi+31h]

8086dd4a 83e2f1          and     edx,0FFFFFFF1h

8086dd4d 0bca            or      ecx,edx

8086dd4f 0b880c020000    or      ecx,dword ptr [eax+20Ch]

8086dd55 3be9            cmp     ebp,ecx

8086dd57 0f85de000000    jne     nt!SwapContext+0x15b (8086de3b)

8086dd5d 8d4900          lea     ecx,[ecx]

8086dd60 f740e400000200  test    dword ptr [eax-1Ch],20000h

8086dd67 7503            jne     nt!SwapContext+0x8c (8086dd6c)

8086dd69 83e810          sub     eax,10h

8086dd6c 8b4b40          mov     ecx,dword ptr [ebx+40h]

8086dd6f 894104          mov     dword ptr [ecx+4],eax

8086dd72 8b6628          mov     esp,dword ptr [esi+28h] //此时esp已是新线程的上次切换时的值。

8086dd75 8b4620          mov     eax,dword ptr [esi+20h]

8086dd78 894318          mov     dword ptr [ebx+18h],eax

8086dd7b fb              sti

8086dd7c 8b4744          mov     eax,dword ptr [edi+44h]

8086dd7f 3b4644          cmp     eax,dword ptr [esi+44h]

8086dd82 c6475000        mov     byte ptr [edi+50h],0

8086dd86 7440            je      nt!SwapContext+0xe8 (8086ddc8)

8086dd88 8b7e44          mov     edi,dword ptr [esi+44h] //注意:edi改为新线程的EPROCESS

8086dd8b 8b4b48          mov     ecx,dword ptr [ebx+48h]

8086dd8e 314834          xor     dword ptr [eax+34h],ecx

8086dd91 314f34          xor     dword ptr [edi+34h],ecx

8086dd94 66f74720ffff    test    word ptr [edi+20h],0FFFFh

8086dd9a 7571            jne     nt!SwapContext+0x12d (8086de0d)

8086dd9c 33c0            xor     eax,eax

8086dd9e 0f00d0          lldt    ax

8086dda1 8d8b40050000    lea     ecx,[ebx+540h]

8086dda7 e850afffff      call    nt!KeReleaseQueuedSpinLockFromDpcLevel (80868cfc)

8086ddac 33c0            xor     eax,eax

8086ddae 8ee8            mov     gs,ax

8086ddb0 8b4718          mov     eax,dword ptr [edi+18h]

8086ddb3 8b6b40          mov     ebp,dword ptr [ebx+40h]

8086ddb6 8b4f30          mov     ecx,dword ptr [edi+30h]

8086ddb9 89451c          mov     dword ptr [ebp+1Ch],eax

8086ddbc 0f22d8          mov     cr3,eax

8086ddbf 66894d66        mov     word ptr [ebp+66h],cx

8086ddc3 eb0e            jmp     nt!SwapContext+0xf3 (8086ddd3)

8086ddc5 8d4900          lea     ecx,[ecx]

8086ddc8 8d8b40050000    lea     ecx,[ebx+540h]

8086ddce e829afffff      call    nt!KeReleaseQueuedSpinLockFromDpcLevel (80868cfc)

8086ddd3 8b4318          mov     eax,dword ptr [ebx+18h]

8086ddd6 8b4b3c          mov     ecx,dword ptr [ebx+3Ch]

8086ddd9 6689413a        mov     word ptr [ecx+3Ah],ax

8086dddd c1e810          shr     eax,10h

8086dde0 88413c          mov     byte ptr [ecx+3Ch],al

8086dde3 88613f          mov     byte ptr [ecx+3Fh],ah

8086dde6 ff464c          inc     dword ptr [esi+4Ch]

8086dde9 ff831c060000    inc     dword ptr [ebx+61Ch]

8086ddef 59              pop     ecx//<---------本线程ESP+4

8086ddf0 890b            mov     dword ptr [ebx],ecx

8086ddf2 807e4900        cmp     byte ptr [esi+49h],0

8086ddf6 7504            jne     nt!SwapContext+0x11c (8086ddfc)

8086ddf8 9d              popfd   //<---------本线程ESP+4

8086ddf9 33c0            xor     eax,eax

8086ddfb c3              ret

 

我们主要来分析保存在线程KernelStack中的ESP堆栈的状态:

 

pjf获得SwapContext地址方法的解析_第1张图片

 

KernelStackETHREAD0x28处:

 

nt!_ETHREAD

   +0x000 Tcb              : _KTHREAD

      +0x000 Header           : _DISPATCHER_HEADER

         +0x000 Type             : UChar

         +0x001 Absolute         : UChar

         +0x002 Size             : UChar

         +0x003 Inserted         : UChar

         +0x004 SignalState      : Int4B

         +0x008 WaitListHead     : _LIST_ENTRY

            +0x000 Flink            : Ptr32

            +0x004 Blink            : Ptr32

      +0x010 MutantListHead   : _LIST_ENTRY

         +0x000 Flink            : Ptr32

         +0x004 Blink            : Ptr32

      +0x018 InitialStack     : Ptr32

      +0x01c StackLimit       : Ptr32

      +0x020 Teb              : Ptr32

      +0x024 TlsArray         : Ptr32

      +0x028 KernelStack      : Ptr32 ß----此处

      +0x02c DebugActive      : UChar

…………

 

 

因为当前线程已经不是这个结构了,SwapContext8086dd88已经替换了ESP了。所以我们需要找一个非当前线程的PETHREAD,于是

*(PULONG)((PETHREAD->KernelStack) + 8) 就是SwapContext的返回地址了。

Pfj就是HOOK的这个地址。但是需要注意的是此处ESI还是新线程的ETHREAD;但是EDI已经不是旧线程的ETHREAD了,它已在SwapContext中被修改成新线程的EPROCESS(见SwapContext8086dd88)或其他值了。

 

所以若是你若HOOK此处,则只能使用ESI值作为新线程的ETHREADEDI是不能用了。网文《check hidden process(hook SwapContext)》([2])就是在此处出了点问题。

 

其实找到SwapContext地址也不难,可以使用KiSwapContextCall SwapContext指令(8086dbe6 e8f5000000 call nt!SwapContext)SwapContext地址为:

 

 

pSwapContext = *(PULONG)((PETHREAD->KernelStack) + 8);

pSwapContext = pSwapContext + *(PULONG)((ULONG)pSwapContext – 4);

 

 

    HOOK此处的地址,ESI就是新线程的ETHREADEDI就是旧线程的ETHREAD了。

 

参考文献:

[1]. http://pjf.blogcn.com/diary,109827361.shtml

[2]. http://www.antiprote ct.com/printer_friendly_posts.asp?TID=4

你可能感兴趣的:(c,list,汇编,header,byte,hook)