目录
总概:
这个变形乱序写了部分时间了,但是一直断断续续,又有期末考试,所以写的很慢,现在也算是完成了部分功能了。
1、能够对部分类型代码进行变形,后期加入更多的模板实现所有指令变形。
2、能够隐藏常量,比如mov eax,0x12345678这类。
3、代码乱序。
4、加入花指令。
5、支持多次变形。
6、能对指定的代码段变形。
原理部分:
用反汇编引擎扫描代码段,将变形乱序的代码转移到新增的区段。
1、乱序部分:
这里我暂时没有将转移指令变形,如果要实现变形也很简单,拿一部分区段的空间保存目的和源地址,然后程序运行时候解密这部分的地址,再进行跳转。我这里是直接改的跳转指令的地址,这样其实比变形的工作量会增大,因为要一直维护这一个跳转地址的list,每次前后指令长度变化都得更新,如果是选择变形后加密存放跳转地址,只用更新保存的地址就可以,工作量减少很多。
实际操作的思路是:首先反汇编引擎扫描一下需要变形的代码区域,将跳转指令保存到一个list中,然后这里将jcc指令(70-7F的这部分),以及0xE8这种都是短跳转一字节的变形为0F 80 - 0F 8F和0xE9这种四字节跳转指令,这个的原因是后面如果变形的话跳转长度超过0xFF,那么这个短跳转就不够用,这里暂时还没处理loopne和jecxz这两个指令,这两个指令只能进行模拟出来。
接着乱序部分是随机将几条指令放置在一个块中,然后跳转到另外一个块中,这里我创建了一个4个0x1000大小的块,乱序即随机抽取几条指令放置在这几个0x1000的块中,如果空间不够容纳抽取的这几条指令则向下再申请4个0x1000大小的块。
//跳转块的结构
typedef struct Jmpblock //代码乱序的Jmp块信息
{
DWORD dwSpaceSize; //块区域的剩余大小
DWORD dwStartAddr; //块开始的地址
DWORD dwEndAddr; //块结束的地址
}Jmpblock, *PJmpblock;
接着是对指令的跳转目的地址的更新,这里指令Instr结构如下:
typedef struct Instr //变形范围内每条指令的信息
{
Opcode opcode;
list<Opcode> lst_opcode; //存放变形后指令的List,没变形就是空
list<DWORD> lst_addr_bejmp; //有范围内指令跳转到这里
DWORD addr_crt; //指令块实时的地址
DWORD addr_ori; //原本的指令地址
}Instr, *PInstr;
lst_addr_bejmp这一成员是保存从上跳转到下面的指令地址信息,addr_crt是保存指令乱序后的实际地址,addr_ori是保存指令的原来地址。更新跳转地址时候,从低地址指令开始逐渐更新到高地址指令地址,因为低地址指令的变形或者乱序会影响后面指令的目的跳转地址,所以这里会分为几种情况处理:
1、如果是向高地址跳转,就将目的地址的lst_addr_bejmp中添加当前指令地址。
2、如果是向低地址跳转,就修改跳转的偏移。
3、如果当前指令的lst_addr_bejmp不为空,那么就得回去更新跳转过来的那些指令的偏移。
4、如果跳转目的地址在原跳转指令范围外,那么则直接修改偏移。
2、变形部分:
对这部分的代码变形:
00460CD3 > 55 push ebp
00460CD4 8BEC mov ebp, esp
00460CD6 6A FF push -0x1
00460CD8 68 98B14800 push 0048B198
00460CDD 68 9C5A4600 push 00465A9C
变形后:
004C2000 81ec 03000000 sub esp, 0x3
004C2006 9C pushfd
004C2007 C78424 FDFFFFFF>mov dword ptr [esp-0x3], 0x8788C20
004C2012 81c4 f3ffffff add esp, -0xd
004C2018 FF7424 5E push dword ptr [esp+0x5E]
004C201C 89BC24 F9FFFFFF mov dword ptr [esp-0x7], edi
004C2023 8DA424 FBFFFFFF lea esp, dword ptr [esp-0x5]
004C202A 8F8424 01FFFFFF pop dword ptr [esp-0xFF]
004C2031 8F8424 5EFFFFFF pop dword ptr [esp-0xA2]
004C2038 C78424 F4FFFFFF>mov dword ptr [esp-0xC], 0x20877F
004C2043 66:8F8424 B6FFF>pop word ptr [esp-0x4A]
004C204B 8F8424 C0FFFFFF pop dword ptr [esp-0x40]
004C2052 8F8424 71FFFFFF pop dword ptr [esp-0x8F]
004C2059 81ec fdffffff sub esp, -0x3
004C205F 44 inc esp
004C2060 81ec feffffff sub esp, -0x2
004C2066 81ec ffffffff sub esp, -0x1
004C206C 89AC24 00000000 mov dword ptr [esp], ebp
004C2073 54 push esp
004C2074 5D pop ebp
004C2075 FF7424 A2 push dword ptr [esp-0x5E]
004C2079 8DA424 FAFFFFFF lea esp, dword ptr [esp-0x6]
004C2080 68 8EE49319 push 0x1993E48E
004C2085 8F8424 FCFFFFFF pop dword ptr [esp-0x4]
004C208C 66:FF7424 1D push word ptr [esp+0x1D]
004C2091 66:56 push si
004C2093 68 3C58D406 push 0x6D4583C
004C2098 8F8424 F6FFFFFF pop dword ptr [esp-0xA]
004C209F FF7424 E9 push dword ptr [esp-0x17]
004C20A3 8DA424 FFFFFFFF lea esp, dword ptr [esp-0x1]
004C20AA C78424 0F000000>mov dword ptr [esp+0xF], -0x1
004C20B5 899C24 FEFFFFFF mov dword ptr [esp-0x2], ebx
004C20BC 8F8424 35FFFFFF pop dword ptr [esp-0xCB]
004C20C3 8DA424 07000000 lea esp, dword ptr [esp+0x7]
004C20CA 81ec feffffff sub esp, -0x2
004C20D0 81c4 02000000 add esp, 0x2
004C20D6 E8 00000000 call 004C20DB
004C20DB 66:68 8948 push 0x4889
004C20DF 66:50 push ax
004C20E1 66:60 pushaw
004C20E3 8DA424 E3FFFFFF lea esp, dword ptr [esp-0x1D]
004C20EA 898C24 2C000000 mov dword ptr [esp+0x2C], ecx
004C20F1 66:68 292A push 0x2A29
004C20F5 52 push edx
004C20F6 C78424 37000000>mov dword ptr [esp+0x37], 0048B198
004C2101 68 31A78610 push 0x1086A731
004C2106 8F8424 F8FFFFFF pop dword ptr [esp-0x8]
004C210D 8F8424 CCFFFFFF pop dword ptr [esp-0x34]
004C2114 81c4 03000000 add esp, 0x3
004C211A 8F8424 D5FFFFFF pop dword ptr [esp-0x2B]
004C2121 C78424 FCFFFFFF>mov dword ptr [esp-0x4], 0x4B011A6
004C212C 8F8424 FCFFFFFF pop dword ptr [esp-0x4]
004C2133 68 319F570B push 0xB579F31
004C2138 8F8424 F4FFFFFF pop dword ptr [esp-0xC]
004C213F 66:8F8424 F1FFF>pop word ptr [esp-0xF]
004C2147 8F8424 6BFFFFFF pop dword ptr [esp-0x95]
004C214E 68 46DC5906 push 0x659DC46
004C2153 8F8424 F9FFFFFF pop dword ptr [esp-0x7]
004C215A 81ec faffffff sub esp, -0x6
004C2160 81c4 03000000 add esp, 0x3
004C2166 66:8F8424 D1FFF>pop word ptr [esp-0x2F]
004C216E 68 2D29DD2A push 0x2ADD292D
004C2173 8F8424 02000000 pop dword ptr [esp+0x2]
004C217A 81ec f6ffffff sub esp, -0xa
004C2180 81c4 01000000 add esp, 0x1
004C2186 8DA424 01000000 lea esp, dword ptr [esp+0x1]
004C218D 81ec ffffffff sub esp, -0x1
004C2193 44 inc esp
004C2194 899C24 F7FFFFFF mov dword ptr [esp-0x9], ebx
004C219B 81EC F8FFFFFF sub esp, -0x8
004C21A1 81ec ffffffff sub esp, -0x1
004C21A7 66:FF7424 1E push word ptr [esp+0x1E]
004C21AC 81c4 fdffffff add esp, -0x3
004C21B2 FF7424 45 push dword ptr [esp+0x45]
004C21B6 68 2CF30E02 push 0x20EF32C
004C21BB 8F8424 02000000 pop dword ptr [esp+0x2]
004C21C2 66:68 FA79 push 0x79FA
004C21C6 68 98012D17 push 0x172D0198
004C21CB 8F8424 FDFFFFFF pop dword ptr [esp-0x3]
004C21D2 8DA424 F2FFFFFF lea esp, dword ptr [esp-0xE]
004C21D9 68 430FE52C push 0x2CE50F43
004C21DE 8F8424 00000000 pop dword ptr [esp]
004C21E5 81ec 02000000 sub esp, 0x2
004C21EB 68 7745F500 push 0xF54577
004C21F0 8F8424 FFFFFFFF pop dword ptr [esp-0x1]
004C21F7 8DA424 FEFFFFFF lea esp, dword ptr [esp-0x2]
004C21FE C78424 19000000>mov dword ptr [esp+0x19], 00465A9C
004C2209 8DA424 0D000000 lea esp, dword ptr [esp+0xD]
004C2210 8DA424 05000000 lea esp, dword ptr [esp+0x5]
004C2217 8DA424 03000000 lea esp, dword ptr [esp+0x3]
004C221E 66:8F8424 5BFFF>pop word ptr [esp-0xA5]
004C2226 81ec feffffff sub esp, -0x2
这里只变形了一次,并且没有对常量进行隐藏也没有加花指令。
主要原理:在push指令中随机插入抬高堆栈的指令降低堆栈的指令以及对堆栈进行随机写入值和寄存器。将mov指令也全部转到堆栈上来实现,这样做了之后可以在以后的变形中实现多次变形,这样随机插入的抬高栈顶的指令和一些mov指令能够得到二次变形,这样变形之后还原的难度会比较大,只能搜集模板写一个能还原的工具来还原,人工还原基本不现实,这样干扰分析的目的就达到了,并不是说变形后代码就能绝对安全,只能是干扰作用,增大逆向的成本。
1、抬高堆栈的方法随机选择以下几种:
指令 抬高的大小(字节)
pushfd -> 4
pushfw -> 2
pushad -> 0x20
pushaw -> 0x10
sub esp,+x -> x
add esp,-x -> x
push dw[esp+x]-> 4
push w[esp+x] -> 2
push reg32 -> 4
push reg16 -> 2
push imm32 -> 4
push imm16 -> 2
lea esp,[esp+x]-> x
call $+5 -> 4
dec esp -> 1
2、降低堆栈的方法随机选择以下几种:
指令 降低的大小(字节)
sub esp,-x -> x
add esp,+x -> x
lea esp,[esp+x]-> x
pop dw[esp+x] -> 4
pop w[esp+x] -> 2
inc esp -> 1
具体的变形细节就字行发挥去想一些模块,我这里所有指令的变形都变形到堆栈上,再对其进行多次变形,这样就会很大的增加分析的难度。
3、隐藏常量:
原理:将带有常量的语句进行变形,首先随机选择一个数,对这个数随机的进行xor,and,or,sub,add,rol,ror这些操作,然后在最后一步的时候将这个数和原来的数计算出差值,再选择一种计算指令,还原到到原来的数。
比如一条push 0xFF指令,变形后:
004C2160 9C pushfd
004C2161 68 BCC5D50D push 0xDD5C5BC
004C2166 59 pop ecx
004C2167 81E9 4F8B2F06 sub ecx, 0x62F8B4F
004C216D c1c1 ce rol ecx, 0xce
004C2170 81F1 0D3B2006 xor ecx, 0x6203B0D
004C2176 81C9 3389F707 or ecx, 0x7F78933
004C217C 81F1 096F4E17 xor ecx, 0x174E6F09
004C2182 81C1 AC7BB324 add ecx, 0x24B37BAC
004C2188 81C9 BC555205 or ecx, 0x55255BC
004C218E c1c1 44 rol ecx, 0x44
004C2191 81F1 C4C3F113 xor ecx, 0x13F1C3C4
004C2197 81E9 309784C4 sub ecx, 0xC4849730
004C219D 9D popfd
004C219E 870C24 xchg dword ptr [esp], ecx
下面的是进行变形的一个Demo: