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
posted @ 2007-11-29 09:06  至尊王者  阅读(1174)  评论(0编辑  收藏  举报