一般的可執行惡意樣本的INT(導入名稱表)在一定程度上就暴露了自己的行爲,所以又來保護自己了。下面是一個樣本中的實際應用,從PE文件結構入手。爲了可以調用相關的API (由kernel32.dll ,ntdll.dll等導出,它先找到目標dll在內存中加載的地址(這些系統dll已經有系統加載到內存中),然後就是根據PE文件結構一頓操作,主要是通過導出名稱字符生成一個DWORD數去比對,在找到FuncAddr。下面是相關操作的反彙編代碼:
GetModuleAddr proc near
push ebp
mov ebp,esp
mov eax,large fs:30h ;fs 寄存器指向當前線程環境塊,是內核的結構,可以通過WinDbg去詳細查看。在偏移爲30h 的地方是Teb->ProcessEnvironmentBlock 進程環境塊
mov eax,[eax+0ch] ; Peb->Ldr
mov eax,[eax+1ch];Ldr->InitializationOrderModuleList
mov eax,[eax+8] ;由於系統的版本不一樣,同一個dll加載的順序可能不一樣
pop ebp
retn
GetModuleAddr endp
;通過名稱在ENT中找到該函數的導出序號,再去EAT得到地址就可以調用了
GetFuncAddr proc near
var_24 = dword ptr -24h
var_20 = dword ptr -20h
var_1C = dword ptr -1Ch
var_18 = dword ptr -18h
var_14 = dword ptr -14h
var_10 = dword ptr -10h ;該函數用的變量
var_C = dword ptr -0Ch
var_8 = dword ptr -8
ExportDirectory = dword ptr -4
arg_0 = dword ptr 8
arg_4 = dword ptr 0Ch;3個參數
Addr = dword ptr 10h
;可以對照PE結構文檔看
push ebp
mov ebp, esp
sub esp, 24h
mov eax, [ebp+arg_0];模塊地址
mov eax, [eax+3Ch] ;3c---ImageDosHeader->e_lfanew PE文件頭的偏移
mov ecx, [ebp+arg_0]
lea eax, [ecx+eax+18h];[eax+ecx]是PE文件頭的地址,再加上18h 是擴展頭的地址
mov [ebp+var_10], eax
mov eax, [ebp+var_10] ; OptionalHeader
mov ecx, [ebp+arg_0]
add ecx, [eax+60h] ;IMAGE_DATA_DIRECTORY
mov [ebp+ExportDirectory], ecx
mov eax, [ebp+arg_4]
shr eax, 10h ;右移10h位
movzx eax, ax ;去低16位
test eax, eax
jnz short loc_402672;是否使用原可執行文件中得到地址
mov eax, [ebp+arg_4]
loc_40265F:
and eax, 0FFFFh
movzx eax, ax
mov ecx, [ebp+ExportDirectory]
sub eax, [ecx+10h] ; Base
mov [ebp+var_C], eax
jmp short loc_4026E9
loc_402672:
mov eax, [ebp+ExportDirectory]
mov ecx, [ebp+arg_0]
add ecx, [eax+20h] ; AddressOfNames
mov [ebp+var_1C], ecx
mov eax, [ebp+ExportDirectory]
mov ecx, [ebp+arg_0]
add ecx, [eax+24h] ; AddressOfNameOrdinals
mov [ebp+var_24], ecx
and [ebp+var_20], 0
jmp short loc_4026A8
loc_402690:
mov eax, [ebp+var_20]
inc eax
mov [ebp+var_20], eax
mov eax, [ebp+var_1C]
add eax, 4
mov [ebp+var_1C], eax
mov eax, [ebp+var_24]
inc eax
inc eax
mov [ebp+var_24], eax
loc_4026A8:
mov eax, [ebp+ExportDirectory]
mov ecx, [ebp+var_20]
cmp ecx, [eax+18h];NumberOfNames
jnb short loc_4026DA ;是否超過了導出名稱數
push [ebp+arg_4]
mov eax, [ebp+var_1C]
mov ecx, [ebp+arg_0]
add ecx, [eax]
push ecx
call CompareStr ;匹配成功返回1
pop ecx
pop ecx
movzx eax, al
test eax, eax
jz short loc_4026D8
mov eax, [ebp+var_24]
movzx eax, word ptr [eax]
mov [ebp+var_C], eax;var_c目標序號
jmp short loc_4026DA
loc_4026D8:
jmp short loc_402690 ;匹配失敗,往回走
loc_4026DA:
mov eax, [ebp+ExportDirectory]
mov ecx, [ebp+var_20]
cmp ecx, [eax+18h]
jnz short loc_4026E9
xor eax, eax
jmp short locret_402715
loc_4026E9:
mov eax, [ebp+ExportDirectory]
mov ecx, [ebp+arg_0]
add ecx, [eax+1Ch] ; AddressOfFunctions
mov [ebp+var_8], ecx
mov eax, [ebp+var_C]
mov ecx, [ebp+var_8]
mov eax, [ecx+eax*4] ;最後從EAT中取出地址
mov [ebp+var_18], eax
mov eax, [ebp+arg_0]
add eax, [ebp+var_18]
mov [ebp+var_14], eax
mov eax, [ebp+Addr]
mov ecx, [ebp+var_14]
mov [eax], ecx
xor eax, eax
inc eax ; succeed
locret_402715:
leave
retn
GetFuncAddr endp