_ _ (_) | | __ ____ __ _ _ _ _ __ ___ _ __ _ __ ___ | |_ \ \ / /\ \/ /| || | | || '_ ` _ \ | '_ \ | '_ \ / _ \| __| \ V / > < | || |_| || | | | | || |_) |_ | | | || __/| |_ \_/ /_/\_\| | \__,_||_| |_| |_|| .__/(_)|_| |_| \___| \__| _/ | | | |__/ |_| /---------------------------------------------------------------------------------------\ |>...................[ 实战多态变形学 1 ]...................<| |>......................[ by Anskya/vxjump.net ].........................<| |>......................[ 2010-03-18 ].........................<| \>...................... [ Anskya@Gmail.com ] ..........................>作者: Anskya[VxJump] 转载保留版权 捣鼓vx也有段时间了.一直没有扔出点有价值的东西. 作为技术科普这里放出一套自己学习的笔记... <<实战多态变型>> 文章分为好几章,科普一下传说中的多态变型技术. 有啥用?除了病毒,还有ShellCode变型, 加壳技术中虚拟,变异,混乱.几乎都是从多态变型技术上发展出来的. 这里文章的开始.有几点需要交代. 1.希望大家有一些Ia32 asm基础 2.对C语言或者pascal有一定了解 3.这里是pascal描述,看不懂的恶补一下 4.这里会分析和描述一些经典的多态引擎的架构和设计. 5.工作平台是Windows XPSP3,使用的调试器Ollydbg,编译器:Delphi7SE 6.作为科普会提供演示代码,请勿用于非法用途,仅供学习与测试. (如果使用这里所提供的代码引发例如: XX洋海啸,X极冰山融化,X星碰撞X球, XX气体排放超标,X水没有过滤就排入江河湖海 等等问题请自行负责.本人概不负责...) 7.没事就看看吧,权当娱乐了... [多态引擎的分类-从简单到复杂---感谢各位大牛提供的分级理论] 0.解密代码.执行 1.解密程序包含,一个或者几个不变的指令.其他的都可以改变 2.解密程序会填充一些垃圾指令(例如一些没有实际意义的代码,mov eax, eax, nop, add eax, 0等等) 3.随机使用寄存器(计数,地址存储寄存器),改变执行顺序-随机调整所用寄存器(例如eax-换成ecx等) 4.会替换和改变代码执行顺序,和相同功能的代码(这里开始代码变型了.变型引擎需要用到的技术) 5.加入反汇编,反调试指令.未知指令(实际意义不大.)抗虚拟机模拟和反汇编引擎识别 6.分段加密-实际意义不是很大 7.随机生成解密算法.例如ETMS 0.36,吗啡的引擎-可以随机生成解密算法-XOR,SUB,ADD.等指令随机生成 8.使用高级指令,MMX,3DNow,SSE(1-5),P5,P6指令等等--例如MMXE引擎就采用MMX指令来作为解密运算指令 9.反虚拟机,反跟踪(大部分Axer都是在虚拟机下调试的(您不是?膜拜).反虚拟机反跟踪.势在必行.) //Anti-Virus的虚拟机脱壳或者检测系统不可能完美模拟操作系统和CPU的所有特性. //所以我们还是有许多事情可以做的(嘿嘿~~~) A.更高级的指令模拟, B.利用一些CPU,OS特殊特性做到改变解密流程-例如那个利用CPU缓存相当猥琐.其实还有许多许多方法 [第一章构造一个最简单的多态引擎] 这里设计一个简单的代码: [code] mov eax, 12345678h ;记录下需要解密代码地址 mov ecx, 8h ;数据长度(这里是解密长度=数据长度 / 4) @Loop_Xor: xor [eax], 87654321h;做解密运算.这里的87654321h-是密钥-当然可以自己改变了 add eax, 4 ;如此这般. sub ecx, 1 ;让ecx-1的指令很多-是不是有许多思路了?dec ecx,add ecx, -1等等 cmp ecx, 0 ;这里也许多or ecx, ecx,test ecx, ecx等等 jnz @Loop_Xor ;当然你也可以使用loop-方便指令替换这里采用jnz mov eax, 12345678h ;记录下OEP的地址(这里可以优化的.我只是为了看着清晰才这么写的) jmp eax ;goto oep [/code] [2.生成代码] 上面的代码几乎都看懂了吧?看不懂?那没办法您还是恶补一下asm基础知识吧 这里我们构造的引擎.执行后原始地址代码就解密出来了.-具体调试一下例子代码(见附件) 说说如何生成代码.当然大家都知道asm实际上就是16进制的XXX翻译过来的.这个结构我们叫他opcode 不熟悉没关系.多用用反汇编工具你就会发现.这些指令还是有规律的 几乎人人都知道nop=90h,C3=retn,这个就是了. 其他的指令也一样.见下面的代码 [code] 0040376F |. B8 78563412 mov eax, 12345678---解密代码地址(这个是一开始设定好的.直接生成) 00403774 |. B9 08000000 mov ecx, 8 00403779 |. 8130 21436587 xor dword ptr [eax], 87654321 0040377F |. 83C0 04 add eax, 4--改变解密指针步进 00403782 |. 83E9 01 sub ecx, 1--计数器-1 00403785 |. 83F9 00 cmp ecx, 0--判断是否解密完毕 00403788 |. 75 EF jnz short 00403779--如果没有解密完毕的话就继续解密 00403963 . B8 78563412 mov eax, 12345678---可以goto OEP了 00403968 . FFE0 jmp eax [/code] 是不是看的很清楚? B8 78563412 mov eax, 12345678--这里就可以解析了. B8=mov操作符,78563412=12345678(内存反过来的.) 可以使用一些高级的反汇编工具对照着看.也可以参考Intel的说明书好好看.或者网上有不少opcode的教程 一目了然可以改变的地方几乎都出现了.标注出来的下面就是代码生成部分了 [code] PByte(lpDst)^ := $B8; Inc(PByte(lpDst)); PDword(lpDst)^ := $12345678; Inc(PDword(lpDst)); [/code] 这样就可以自己构造出一句mov eax, xxxx的指令了.是不是很简单?本来就很简单 下面解密计数器-mov ecx, 8也可以这样构造. 看不懂pascal?给出asm吧 [code] asm mov edi, lpDst mov al, 0B8h stosb ;不少多态引擎里面都是这么写的.嘛~如果你熟悉的话自然就知道什么意思 mov eax, 12345678h stosd end; [/code] Virus为了减少程序体积大部分多态引擎都是asm写的,加壳软件和现在的许多新的多态引擎都是高级语言写的 反正熟悉opcode结构自己用什么语言描述只是个习惯问题. 按照上面所说的自己构造一个好了 我已经构造好了.见附件 这里需要注意的就是jnz 指令. jnz指令是无视自己的.就是说jnz rel8-这里采用短跳转,如果你需要可以自己扩展成长跳转. jnz @1 ---这里的16进制是75 00-因为他不需要计算自己-自己长2-如果长跳转的话也是这么计算 @1: jnz @1 ---这里是75 FE-证实以上说法.由于不计算自身.所以就得跳转$-2的地址 (往高位跳转是整数,低位就是负数啦)计算出来就是FE=0-2 代码生成原理搞懂了.这里作为方便大家利用写了一个代码生成引擎(见附件)-以后写方便 [code] // mov eax, 12345678h Mov_Reg32_Imm32(lpSeek, Reg_Eax, dwRunVA); // mov ecx, 8(这里采用xor dword来加解数据.所以这里的数据长度为dwLen div 4) Mov_Reg32_Imm32(lpSeek, Reg_Ecx, dwLen div 4); // xor dword ptr [eax], 87654321 lpJnz := lpSeek; Xor_ModReg32_Imm32(lpSeek, Reg_Eax, dwKey); // add eax, 4 Add_Reg32_Imm8(lpSeek, Reg_Eax, 4); // sub ecx, 1 Sub_Reg32_Imm8(lpSeek, Reg_Ecx, 1); // cmp ecx, 0 Cmp_Reg32_Imm8(lpSeek, Reg_Ecx, 0); // jnz short 00403779 Jnz_Rel8(lpSeek, DWORD(lpJnz) - DWORD(lpSeek)); // mov eax, 12345678 Mov_Reg32_Imm32(lpSeek, Reg_Eax, dwRunVA); // jmp eax Jmp_Reg32(lpSeek, Reg_Eax); [/code] 可以很容易的生成这些机器码.实际上根据这个原理可以构造出许多Semi-Polymorphic(不少大牛开始奸笑了) .实际上这个和虚拟代码差不多.不少第三方虚拟机和多态生成器就是这么干的 VM_Mov_Reg32_Imm32(xxx, Reg_XXX, XXX);--由于直接在这个过程里面写变换指令 甚至有不少人例如kpasm就是采用这种方式生成的Semi-Poly代码然后虚拟Handler或者Meta生成器 按照这个规则生成--可以直接减少工作量,而且以后扩展规则相当简单...只需要修改规则就好了 以后再慢慢讨论吧.完整代码见附件... 这里加密算法就使用了简单的xor ModReg32, imm32 以后会讲解如何生成随机加密解密算法 值得一提的是kpasm相当强大.几乎就是一个编译器利用yacc和lex来解析自己的多态语言(可以这么叫不?) 然后生成fasm或者tasm的语言,根据规则(就是多态语言编写的规则).来生成一个多态引擎(fasm or tasm) 相当BT.作者用在自己的win32.leon病毒内.嗯很猥琐很强大 当然这些都是构筑在现有的多态变型基础上的 十年了.从BPE32b发展到现在.咱们的Vxer前辈几乎都灭绝了.Vx技术也几乎无人提起了. (现在都走商业了.谁写免费的病毒开源?都高级语言写蠕虫写个XX就敢叫Virus.实在令人无语) 文章我会继续写下去.多态写完,写变型-这种被吹嘘得有点过的技术(在壳中发展的很好),写虚拟机 写感染,希望大家支持 Anskya/VxLab(2010). 感谢我的良师益友:nEINEI[VxJump],玩命,xfish(小鱼姐我们需要您呀...),drocon(好久没出现了) 还有感谢各位捧场能看完我就感谢...