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