AVP主动防御之隐藏进程

卡巴主动防御中检测隐藏进程的方法:

    Hook掉系统的SwapContext,这种方法是在2003年被提出的;这个函数被KiSwapThread调用,负责线程调度;下面这部分代码就是卡巴Detour SwapContext的汇编代码的分析(后面附上对应的c代码):


(PS:突破这种方式来隐藏进程的方法也在随后就出来了,自己实现线程调度,详见:http://hi-tech.nsys.by/33/)


一:KlifSetSwapContextHook


.text:0002DE60 KlifSetSwapContextHook proc near      

.text:0002DE60

.text:0002DE60 var_5C          = dword ptr -5Ch

.text:0002DE60 var_58          = dword ptr -58h

.text:0002DE60 var_54          = dword ptr -54h

.text:0002DE60 var_50          = dword ptr -50h

.text:0002DE60 var_48          = dword ptr -48h

.text:0002DE60 var_38          = dword ptr -38h

.text:0002DE60 var_34          = dword ptr -34h

.text:0002DE60 var_30          = word ptr -30h

.text:0002DE60 var_24          = dword ptr -24h

.text:0002DE60 var_20          = dword ptr -20h

.text:0002DE60 var_1C          = dword ptr -1Ch

.text:0002DE60 var_18          = dword ptr -18h

.text:0002DE60 var_10          = dword ptr -10h

.text:0002DE60 var_4           = dword ptr -4

.text:0002DE60

.text:0002DE60                 push    ebp

.text:0002DE61                 mov     ebp, esp

.text:0002DE63                 push    0FFFFFFFFh

.text:0002DE65                 push    offset dword_13158

.text:0002DE6A                 push    offset sub_2E46C

.text:0002DE6F                 mov     eax, large fs:0

.text:0002DE75                 push    eax

.text:0002DE76                 mov     large fs:0, esp

.text:0002DE7D                 sub     esp, 4Ch

.text:0002DE80                 push    ebx

.text:0002DE81                 push    esi

.text:0002DE82                 push    edi

.text:0002DE83                 mov     [ebp+var_18], esp

.text:0002DE86                 mov     ecx, g_NtoskrnlAddr

.text:0002DE8C                 cmp     word ptr [ecx], 5A4Dh ; Ms dos stub - MZ

.text:0002DE91                 jnz     Routine_Error

.text:0002DE97                 mov     eax, [ecx+3Ch]  ; e_lfanew

.text:0002DE9A                 add     eax, ecx

.text:0002DE9C                 cmp     dword ptr [eax], 4550h ; PE

.text:0002DEA2                 jnz     Routine_Error

.text:0002DEA8                 xor     edx, edx

.text:0002DEAA                 mov     dx, [eax+14h]      ; SizeOfOptionalHeader

.text:0002DEAE                 lea     eax, [edx+eax+18h] ; 指向第一Section(.text)

.text:0002DEB2                 mov     esi, [eax+0Ch]

.text:0002DEB5                 add     esi, ecx           ;.text区的内存地址

.text:0002DEB7                 mov     eax, [eax+10h]     ;.text区的内存大小

.text:0002DEBA                 xor     ebx, ebx

.text:0002DEBC                 mov     [ebp+var_20], ebx

.text:0002DEBF                 mov     [ebp+var_4], ebx

.text:0002DEC2                 mov     ecx, ds:NtBuildNumber

.text:0002DEC8                 mov     cx, [ecx]

.text:0002DECB                 cmp     cx, 2600        ; 1575 - 2195 Win2K

.text:0002DECB                                         ; 2202 - 2600 WinXP

.text:0002DECB                                         ; 3501 - 3790 Win2003

.text:0002DED0                 jle     Is2kORxp

.text:0002DED6                 mov     [ebp+var_1C], 5

.text:0002DEDD                 cmp     cx, 3790

.text:0002DEE2                 jl      short Is2003Release

.text:0002DEE4                 mov     ecx, offset g_2003CharCode ; 2003的特征码

.text:0002DEE9                 mov     [ebp+var_58], ecx

.text:0002DEEC                 mov     edx, 9

.text:0002DEF1                 mov     [ebp+var_54], edx

.text:0002DEF4                 xor     edi, edi

.text:0002DEF6                 jmp     short Is2003

.text:0002DEF8

.text:0002DEF8 Is2003Release:

.text:0002DEF8                 cmp     cx, 3604

.text:0002DEFD                 jle     short Is2003Beta3

.text:0002DEFF                 mov     ecx, offset g_ReleaseCharCode ; 2003Beat3-Release的特征码

.text:0002DF04                 mov     [ebp+var_58], ecx

.text:0002DF07                 mov     edx, 8

.text:0002DF0C                 mov     [ebp+var_54], edx

.text:0002DF0F                 mov     edi, 0Ah

.text:0002DF14                 jmp     short Is2003

.text:0002DF16

.text:0002DF16 Is2003Beta3:

.text:0002DF16                 mov     ecx, offset g_Bete3CharCode ; 2003的Beta-Beta3特征码

.text:0002DF1B                 mov     [ebp+var_58], ecx

.text:0002DF1E                 mov     edx, 7

.text:0002DF23                 mov     [ebp+var_54], edx

.text:0002DF26                 mov     edi, 9

.text:0002DF2B

.text:0002DF2B Is2003:

.text:0002DF2B                 mov     [ebp+var_50], edi

.text:0002DF2E                 push    edx

.text:0002DF2F                 push    ecx

.text:0002DF30                 push    eax

.text:0002DF31                 push    esi

.text:0002DF32                 call    KilfGetAddrByCharCode ; arg_c 特征码的长度

.text:0002DF32                                               ; arg_8 特征码的地址

.text:0002DF32                                               ; arg_4 搜索的最大范围

.text:0002DF32                                               ; arg_0 搜索的起始地址

.text:0002DF37                 mov     [ebp+var_24], eax

.text:0002DF3A                 cmp     eax, 0FFFFFFFFh

.text:0002DF3D                 jz      Search_Failed

.text:0002DF43                 add     eax, edi

.text:0002DF45                 add     esi, eax

.text:0002DF47                 cmp     dword ptr [esi], 0FF1043FFh

.text:0002DF4D                 jnz     short Search_Failed

.text:0002DF4F                 mov     ebx, esi

.text:0002DF51                 mov     [ebp+var_20], ebx

.text:0002DF54                 mov     [ebp+var_4], 0FFFFFFFFh

.text:0002DF5B                 jmp     SetSwapContextHook

.text:0002DF60

.text:0002DF60 Is2kORxp:

.text:0002DF60                 push    5

.text:0002DF62                 push    offset g_2kCharCode ; 2k的特征码

.text:0002DF67                 push    eax

.text:0002DF68                 push    esi

.text:0002DF69                 call    KilfGetAddrByCharCode ; arg_c 特征码的长度

.text:0002DF69                                               ; arg_8 特征码的地址

.text:0002DF69                                               ; arg_4 搜索的最大范围

.text:0002DF69                                               ; arg_0 搜索的起始地址

.text:0002DF6E                 mov     [ebp+var_24], eax

.text:0002DF71                 cmp     eax, 0FFFFFFFFh

.text:0002DF74                 jz      short Search_Failed

.text:0002DF76                 mov     edx, ds:NtBuildNumber

.text:0002DF7C                 cmp     word ptr [edx], 2195

.text:0002DF81                 jle     short Is2k

.text:0002DF83

.text:0002DF83 Isxp:

.text:0002DF83                 add     esi, eax

.text:0002DF85                 mov     [ebp+var_5C], esi

.text:0002DF88                 mov     [ebp+var_1C], 7

.text:0002DF8F                 push    4

.text:0002DF91                 push    offset g_XpCharCode ; xp的特征码

.text:0002DF96                 push    100h

.text:0002DF9B                 push    esi

.text:0002DF9C                 call    KilfGetAddrByCharCode ; arg_c 特征码的长度

.text:0002DF9C                                               ; arg_8 特征码的地址

.text:0002DF9C                                               ; arg_4 搜索的最大范围

.text:0002DF9C                                               ; arg_0 搜索的起始地址

.text:0002DFA1                 mov     [ebp+var_24], eax

.text:0002DFA4                 cmp     eax, 0FFFFFFFFh

.text:0002DFA7                 jz      short Search_Failed

.text:0002DFA9                 lea     ebx, [esi+eax+2]

.text:0002DFAD                 mov     [ebp+var_20], ebx

.text:0002DFB0                 mov     [ebp+var_4], 0FFFFFFFFh

.text:0002DFB7                 jmp     short SetSwapContextHook

.text:0002DFB9

.text:0002DFB9 Is2k:

.text:0002DFB9                 lea     ebx, [eax+esi]

.text:0002DFBC                 mov     [ebp+var_20], ebx

.text:0002DFBF                 mov     [ebp+var_1C], 5

.text:0002DFC6

.text:0002DFC6 Search_Failed:

.text:0002DFC6                 mov     [ebp+var_4], 0FFFFFFFFh

.text:0002DFCD                 jmp     short SetSwapContextHook

.text:0002DFCF

.text:0002DFCF SEH_Routine:    

.text:0002DFCF                 mov     eax, 1

.text:0002DFD4                 retn

.text:0002DFD5

.text:0002DFD5 SEH_Routine2:      

.text:0002DFD5                 mov     esp, [ebp-18h]

.text:0002DFD8                 mov     dword ptr [ebp-4], 0FFFFFFFFh

.text:0002DFDF                 mov     ebx, [ebp-20h]

.text:0002DFE2

.text:0002DFE2 SetSwapContextHook:

.text:0002DFE2                 test    ebx, ebx

.text:0002DFE4                 jz      Routine_Error

.text:0002DFEA                 mov     eax, 90909090h

.text:0002DFEF                 mov     [ebp+var_38], eax

.text:0002DFF2                 mov     [ebp+var_34], eax

.text:0002DFF5                 mov     [ebp+var_30], ax

.text:0002DFF9                 mov     byte ptr [ebp+var_38], 0E9h ; JMP

.text:0002DFFD                 mov     ecx, offset KlifSwapContext

.text:0002E002                 sub     ecx, ebx        ; EBX是SwapContext+offset的地址

.text:0002E004                 sub     ecx, 5

.text:0002E007                 mov     [ebp+var_38+1], ecx

.text:0002E00A

.text:0002E00A Klif_Store_SC_Addr:                     ; 保存原来的指令

.text:0002E00A                 mov     ecx, [ebp+var_1C]

.text:0002E00D                 lea     edx, [ecx+ebx]

.text:0002E010                 mov     g_SwapContextAddr, edx

.text:0002E016                 mov     esi, ebx

.text:0002E018                 mov     edi, offset g_SwapContextOpcode

.text:0002E01D                 mov     eax, ecx

.text:0002E01F                 shr     ecx, 2

.text:0002E022                 rep movsd

.text:0002E024                 mov     ecx, eax

.text:0002E026                 and     ecx, 3

.text:0002E029                 rep movsb

.text:0002E02B                 lea     ecx, [ebp+var_48]

.text:0002E02E                 push    ecx

.text:0002E02F                 push    1

.text:0002E031                 push    ebx

.text:0002E032                 call    KlifSetInterruptStauts

.text:0002E037                 test    al, al

.text:0002E039                 jz      short Routine_Error

.text:0002E03B                 mov     ecx, offset g_kernelLock

.text:0002E040                 call    KlifClearInterruptAndLock

.text:0002E045

.text:0002E045 Klif_Set_SC_Hook:                         ; detour开始

.text:0002E045                 mov     ecx, [ebp+var_1C] ; 覆盖的Opcodes Num

.text:0002E048                 lea     esi, [ebp+var_38] ; Jmp Klif+0x????

.text:0002E04B                 mov     edi, ebx

.text:0002E04D                 mov     edx, ecx

.text:0002E04F                 shr     ecx, 2

.text:0002E052                 rep movsd

.text:0002E054                 mov     ecx, edx

.text:0002E056                 and     ecx, 3

.text:0002E059                 rep movsb

.text:0002E05B                 mov     edx, eax

.text:0002E05D                 mov     ecx, offset g_kernelLock

.text:0002E062                 call    KlifUnLock

.text:0002E067                 lea     eax, [ebp+var_48]

.text:0002E06A                 push    eax

.text:0002E06B                 mov     ecx, [ebp+var_48]

.text:0002E06E                 push    ecx

.text:0002E06F                 push    ebx

.text:0002E070                 call    KlifSetInterruptStauts

.text:0002E075                 mov     al, 1

.text:0002E077                 mov     ecx, [ebp+var_10]

.text:0002E07A                 mov     large fs:0, ecx

.text:0002E081                 pop     edi

.text:0002E082                 pop     esi

.text:0002E083                 pop     ebx

.text:0002E084                 mov     esp, ebp

.text:0002E086                 pop     ebp

.text:0002E087                 retn

.text:0002E088 Routine_Error:                         

.text:0002E088                 xor     al, al

.text:0002E08A                 mov     ecx, [ebp+var_10]

.text:0002E08D                 mov     large fs:0, ecx

.text:0002E094                 pop     edi

.text:0002E095                 pop     esi

.text:0002E096                 pop     ebx

.text:0002E097                 mov     esp, ebp

.text:0002E099                 pop     ebp

.text:0002E09A                 retn

.text:0002E09A KlifSetSwapContextHook endp



二:KlifSwapContext


.text:0002DE10 KlifSwapContext:                      

.text:0002DE10                 pushf

.text:0002DE11                 pusha

.text:0002DE12                 mov     ebp, esp

.text:0002DE14                 sub     esp, 10h

.text:0002DE17                 add     esi, dword_2FC90

.text:0002DE1D                 add     edi, dword_2FC90

.text:0002DE23                 mov     eax, [esi]      ; Address of next thread

.text:0002DE25                 mov     [ebp-8], eax

.text:0002DE28                 mov     eax, [edi]      ; Address of previous thread

.text:0002DE2A                 mov     [ebp-0Ch], eax

.text:0002DE2D                 mov     ecx, offset g_kernelLock

.text:0002DE32                 call    KlifClearInterruptAndLock

.text:0002DE37                 mov     [ebp-4], eax

.text:0002DE3A                 mov     eax, [ebp-8]

.text:0002DE3D                 push    eax             ; Address of next thread

.text:0002DE3E                 call    KlifSwapContextMain ;//MAIN!!!

.text:0002DE43                 mov     edx, [ebp-4]

.text:0002DE46                 mov     ecx, offset g_kernelLock

.text:0002DE4B                 call    KlifUnLock

.text:0002DE50                 add     esp, 10h

.text:0002DE53                 popa

.text:0002DE54                 popf

.text:0002DE55                 jmp     g_OldSwapContext

.text:0002DE5B                 align 10h



三:KlifSetSwapContextHook 对应C代码


PVOID g_NtoskrnlAddr;

char  g_2003CharCode[8]    = {0xFF, 0x43, 0x10, 0xFF, 0x33, 0x83, 0x7B, 0x08};

char  g_ReleaseCharCode[8] = {0x80, 0x7E, 0x5D, 0x00, 0x74, 0x04, 0xF3, 0x90};

char  g_Bete3CharCode[8]   = {0xF7, 0x46, 0x24, 0x01, 0x00, 0x00, 0x00, 0x00};

char  g_2kCharCode[8]      = {0x26, 0xC6, 0x46, 0x2D, 0x02, 0x00, 0x00, 0x00};

char  g_xpCharCode[4]      = {0x8B, 0x0B, 0x83, 0xBB};

int   g_SwapContextOpcode[4] = {0x90909090, 0x90909090, 0x9090FF25, g_SwapContextAddr};

int   g_SwapContextAddr;

char  g_kernelLock;

BOOL KlifSetSwapContextHook()

{

 METUEX ProtectMutex;        //这个不大准确

 int    nOffset          = 0;//特征码距Ntoskrnl的偏移移

 int    nReplaceNum      = 0;//要替换SwapContext几个字节

 char*  pSwapContextAddr = 0;//要替换的地址

 

 int   nCompareNum  = 0;

 char* pCompareCode = 0;

 

 PIMAGE_DOS_HEADER     pImageDos =  (PIMAGE_DOS_HEADER)g_NtoskrnlAddr;

 PIMAGE_NT_HEADERS     pImageNt  =  (PIMAGE_NT_HEADERS)(g_NtoskrnlAddr+pImageDos->e_lfanew);

 PIMAGE_SECTION_HEADER pImageSec =  (PIMAGE_SECTION_HEADER )((char*)pImageNt+pImageNt->FileHeader.SizeOfOptionalHeader);

 

 char* pSearchAddr = (char*)g_NtoskrnlAddr + pImageSec->VirtualAddress;

 int   nSearchArea = pImageSection->SizeOfRawData;

 

 if ((WORD)g_NtoskrnlAddr               == 0x5A4D &&

     (WORD)((char*)g_NtoskrnlAddr+0x3C) == 0x4550)

 {

  return FALSE;

 }

 

 //Windows 2003

 if (*NtBuildNumber > 2600)

 {

  nReplaceNum = 5;

  int nOrgOffset = 0;

  if (*NtBuildNumber >= 3790)

  {

   nCompareNum = 9;

   pCompareCode = g_2003CharCode;

   

  }else

  {

   if (*NtBuildNumber > 3604)

   {

    nOrgOffset   = 10;

    nCompareNum  = 8;

    pCompareCode = g_ReleaseCharCode;

   }else

   {

    nOrgOffset   = 9;

    nCompareNum  = 7;

    pCompareCode = g_Bete3CharCode;

     

   }

  }

  

  nOffset = KilfGetAddrByCharCode(nCompareNum, 

                                  pCompareCode,

                                  nSearchArea,

                                  pSearchAddr);

  if (nOffset == -1)

  {

   return FALSE;

  }

  

  pSwapContextAddr = pSearchAddr + nOffset + nOrgOffset;

  

  if (((int)pSwapContextAddr) != 0xFF1043FF)

  {

   return FALSE;

  }

  

 }else

 {

  //Win2K

  nOffset = KilfGetAddrByCharCode(5,

                                  g_2kCharCode,

                                  nSearchArea,

                                  pSearchAddr);

  if (nOffset == -1)

  {

   return FALSE;

  }

  

  //WinXP

  if (*NtBuildNumber > 2395)

  {

   nOffset = KilfGetAddrByCharCode(4,

                                   g_xpCharCode,

                                   nSearchArea,

                                   pSearchAddr);   

   if (nOffset == -1)

   {

    return FALSE;

   }

   nReplaceNum      = 7;

   pSwapContextAddr = pSearchAddr + nOffset + 2;

  }else

  {

   nReplaceNum      = 5;

   pSwapContextAddr = pSearchAddr + nOffset;

  }

 }

 if (!pSwapContextAddr)

 {

  return FALSE;

 }

 char NewSwapContext[9] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};

 NewSwapContext[0]           = 0xE9;

 ((int)&NewSwapContext[1]) = (int)KlifSwapContext - (int)pSwapContextAddr - 5;


 //保存原来的指令

 g_SwapContextAddr = pSwapContextAddr + nReplaceNum;//跳回来的地址

 for(int i = nReplaceNum; i>0; i--)

 {

  g_SwapContextOpcode[i] = pSwapContextAddr[i];

 }

 

 if (!KlifSetInterruptStauts(pSwapContextAddr, 1, &ProtectMutex))

 {

  return FALSE;

 }


 KlifClearInterruptAndLock(g_kernelLock);


 //覆盖原来指令

 for(i = nReplaceNum; i>0; i–)

 {

  pSwapContextAddr[i] = NewSwapContext[i];

 }

 KlifUnLock(g_kernelLock);

 KlifSetInterruptStauts(pSwapContextAddr, ProtectMutex, &ProtectMutex);

 return TRUE;

}


阐述中存在错误,望指教,谢谢!转载请注明地址 :)



转载于:http://blog.vckbase.com/windowssky