首页
社区
课程
招聘
[原创]VMProtect代码还原技术
发表于: 2010-12-5 01:50 63431

[原创]VMProtect代码还原技术

2010-12-5 01:50
63431
收藏
免费 8
支持
分享
最新回复 (86)
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
51
指令每次都会变化,但是功能相同,在进行匹配时需要进行识别,然后转化成统一的形式。例如下面3段是完全相同的:

movzx eax,byte ptr [esi]
sub esi,1
mov ax,[eax+edi]
sub ebp,2
mov [ebp],ax

mov al, [esi]
mov ax,[eax+edi]
add esi, 0xffffffff
sub ebp,2
mov [ebp],ax

movzx eax,byte ptr [esi]
lea esi,[esi+1]
sub ebp,2
mov ax,[eax+edi]
mov [ebp],ax
2010-12-15 18:10
0
雪    币: 768
活跃值: (540)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
52
要火了,围观~
2010-12-15 19:14
0
雪    币: 301
活跃值: (300)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
53
看着很给力啊,等插件.
2010-12-15 20:05
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
54
也确实是,真不知道vmp把变型的功夫下到哪里去了.
也许是变成基于堆栈的指令以后了.到了那一步,其实破解的难度就小不少了.
下面这两段代码功能也相同
----------------------------------------------------
1689772) 00437b0d btc     dx, D         
1689773) 00437b12 btc     dx, di         
1689774) 00437b16 aas                    
1689775) 00437b17 bsr     ax, ah         
▌1689776) 00437b1b mov     eax, D[ebp]  
1689777) 00437b1e btr     dx, 5         
1689778) 00437b23 inc     dx            
1689779) 00437b26 pushad                 
▌1689780) 00437b27 mov     edx, D[ebp+4]
1689781) 00437b2a mov     B[esp+C], cl   
1689782) 00437b2e bt      dx, 3         
1689783) 00437b33 add     ebp, 8         
1689784) 00437b36 pushfd                 
▌1689785) 00437b37 mov     D[eax], edx  
1689786) 00437b39 mov     B[esp+10], AB  
1689787) 00437b3e lea     esp, D[esp+24]
----------------------------------------------------
211574) 004348d3 rdtsc                  
211575) 004348d5 clc                     
▌211576) 004348d6 mov     eax, D[ebp]   
211577) 004348d9 jmp     4360D9         
211578) 004360d9 shr     dl, 5           
▌211579) 004360dc mov     ecx, D[ebp+4]
211580) 004360df jmp     436780         
211581) 00436780 jmp     43722A         
211582) 0043722a test    ah, 41E8        
211583) 0043722f add     ebp, 8         
211584) 00437232 pushad                  
211585) 00437233 jmp     436984         
211586) 00436984 push    -6E6DA03        
▌211587) 00436989 mov     D[eax], ecx   
211588) 0043698c push    D[esp]         
211589) 0043698f push    -8EC540F        
211590) 00436994 push    ebp            
211591) 00436995 push    3BBC656         
211592) 0043699a lea     esp, D[esp+34]  
------------------------------------------------------
2010-12-15 21:07
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
55
加油吧
离自由之巅还有很远
2010-12-15 22:09
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
56
可以进行反汇编了,不过如果要自动分析虚拟代码的话,需要动态执行才可以,因为jmp指令居然不能静态得到目标地址。
看来还是先做一个VMP专用调试器

disasm:

0040CE8F  pop r5
0040CE90  push 0x472FBBA9
0040CE95  add dword
0040CE96  pop r9
0040CE97  pop r1
0040CE98  pop r4
0040CE99  pop r0
0040CE9A  pop r9
0040CE9B  pop r11
0040CE9C  pop r15
0040CE9D  pop r12
0040CE9E  pop r8
0040CE9F  pop r7
0040CEA0  pop r3
0040CEA1  pop r14
0040CEA2  pop r13
0040CEA3  push r11
0040CEA4  push word 0x0000
0040CEA6  push r5
0040CEA7  push 0x0040CF7E
0040CEAC  add dword
0040CEAD  pop r13
0040CEAE  read word mem byte
0040CEAF  push esp
0040CEB0  read word mem byte
0040CEB1  nand byte
0040CEB2  pop r10
0040CEB3  add byte
0040CEB4  pop r14
0040CEB5  push esp
0040CEB6  read word mem byte
0040CEB7  nand byte
0040CEB8  pop r6
0040CEB9  pop word (byte)r11
0040CEBB  push r14
0040CEBC  push esp
0040CEBD  read dword mem
0040CEBE  nand dword
0040CEBF  pop r11
0040CEC0  push 0xFFFFF7EA
0040CEC3  nand dword
0040CEC4  pop r10
0040CEC5  push r6
0040CEC6  push r6
0040CEC7  nand dword
0040CEC8  pop r13
0040CEC9  push 0x00000815
0040CECC  nand dword
0040CECD  pop r10
0040CECE  add dword
0040CECF  pop r13
0040CED0  pop r10
0040CED1  push 0x21D3A692
0040CED6  push 0x21D2326F
0040CEDB  push esp
0040CEDC  push word (byte)0x04
0040CEDE  push r10
0040CEDF  push 0xFFFFFFBF
0040CEE1  nand dword
0040CEE2  pop r4
0040CEE3  shr dword
0040CEE4  pop r11
0040CEE5  add dword
0040CEE6  pop r14
0040CEE7  read dword mem
0040CEE8  pop r4
0040CEE9  pop r2
0040CEEA  pop r11
0040CEEB  push r4
0040CEEC  push esp
0040CEED  read dword mem
0040CEEE  pop r14
0040CEEF  push esp
0040CEF0  read dword mem
0040CEF1  nand dword
0040CEF2  pop r4
0040CEF3  push 0xDE6C8BCC
0040CEF8  nand dword
0040CEF9  pop r11
0040CEFA  push r14
0040CEFB  push 0x21937433
0040CF00  nand dword
0040CF01  pop r11
0040CF02  nand dword
0040CF03  pop r4
0040CF04  pop r2
0040CF05  push r9
0040CF06  push r5
0040CF07  push r15
0040CF08  push r8
0040CF09  push r0
0040CF0A  push r11
0040CF0B  push r9
0040CF0C  push r10
0040CF0D  push r12
0040CF0E  push r3
0040CF0F  push r7
0040CF10  push 0xB8D04457
0040CF15  push r1
0040CF16  add dword
0040CF17  pop r11
0040CF18  push r5
0040CF19  push r2
0040CF1A  jmp
2010-12-15 22:43
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
57
到这一步恐怕就需要进行优化了.因为代码的膨胀率仍然很高,需要把编译原理中的优化手段都用上了.vmp中的变型应该在字节码这一步,而不是在字节码到生成的汇编码那一步.
字节码到汇编码完成的工作大概是对执行的流程加密.
2010-12-15 23:55
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
58
看来不能静态重组还原,只能先做一个调试器了
连夜搞了一个。这种虚拟机调试器一般下断点很方便,可以下指令断点。

上传的附件:
2010-12-16 12:54
0
雪    币: 107
活跃值: (424)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
59
[QUOTE=accessd;903577]看来不能静态重组还原,只能先做一个调试器了
连夜搞了一个。这种虚拟机调试器一般下断点很方便,可以下指令断点。

[/QUOTE]

还要自己写调试器啊??改写OD插件得了
2010-12-16 14:28
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
60
就是求跳转地址吧.用常规的调试器也可以知道吧.只要在retn处设断点,看它跳转到哪去就可以了吧
2010-12-16 14:53
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
61
58 L 太有柴了
2010-12-16 14:54
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
62
现在不需要常规调试器了,单步执行到JMP位置处时自动显示一下,或者直接设置JMP指令的断点,收集所有执行过的虚拟指令
2010-12-16 15:16
0
雪    币: 89
活跃值: (181)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
63
就是专用 工具也行,,哈哈,,,等等楼上和谐一遍
2010-12-16 15:23
0
雪    币: 1098
活跃值: (193)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
64
[QUOTE=accessd;903577]看来不能静态重组还原,只能先做一个调试器了
连夜搞了一个。这种虚拟机调试器一般下断点很方便,可以下指令断点。

[/QUOTE]

很好,很强大。改天给我玩一下?
2010-12-17 01:46
0
雪    币: 205
活跃值: (64)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
65
牛叉啊..........

坐等LZ出插件
2010-12-17 13:09
0
雪    币: 9136
活跃值: (4560)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
66
加油!加油!加油!加油!
2010-12-17 14:41
0
雪    币: 553
活跃值: (2290)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
67
这样下去,vmp不是真的可以恢复原状?
2010-12-17 16:54
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
68
神马,一切都是浮云
2010-12-18 13:18
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
69
感谢分析,不过还是期待自动的出来
2010-12-27 11:07
0
雪    币: 119
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
70
加油!加油!加油!加油!
2010-12-27 12:15
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
71
就给一个图,逗人说
2011-1-5 12:21
0
雪    币: 284
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
72
给力给力给力!!
2011-1-7 23:48
0
雪    币: 576
活跃值: (1163)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
73
后者才是王道。。当然结合前者一起来会比较快点吧。。直接硬编码一些机器码匹配,编程上是最容易的。。小菜鸟的看法,呵呵
2011-1-21 16:08
0
雪    币: 29
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
74
继续学习!
2011-1-22 06:28
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
75
垃圾指令很好识别,跑一边 Dead Code Elimination 就出来了。
当然还有一个办法是跑Dependency-Analysis(UD-Chain),只保留有有意义的Instructions。Pseudo-Code,主流的基本代码生成的书上都有,代码我就不贴了。

比如我们要取得ECX在VM-Entry以后的UD-Chain:

[11298389] = call 0x10C2CD3A reads [] writes [esp]
[10C2CD3A] = pushfd  reads [esp] writes [esp]
[10C2CD3B] = push dword [esp+0x04] reads [esp] writes [esp]
[10C2CD3F] = pushfd  reads [esp] writes [esp]
[10C2CD40] = mov dword [esp+0x0C] , 0x5BF5C3BA reads [esp] writes []
[10C2CD48] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[10C2CD49] = mov byte [esp+0x04] , bl reads [esp,ebx] writes []
[10C2CD4D] = push eax reads [esp,eax] writes [esp]
[10C2CD4E] = call 0x112D2CC6 reads [] writes [esp]
[112D2CC6] = mov dword [esp+0x30] , 0x29A8A65C reads [esp] writes []
[112D2CCE] = pushfd  reads [esp] writes [esp]
[112D2CCF] = mov byte [esp] , 0xBF reads [esp] writes []
[112D2CD3] = mov dword [esp] , 0x6116C076 reads [esp] writes []
[112D2CDA] = lea esp , dword [esp+0x34] reads [esp] writes [esp]
[112D2CDE] = jmp 0x113673EC reads [] writes []
[113673EC] = jmp 0x1136744D reads [] writes []
[1136744D] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[1136744E] = mov byte [esp+0x0C] , 0x10 reads [esp] writes []
[11367453] = mov byte [esp] , 0x68 reads [esp] writes []
[11367457] = mov dword [esp+0x1C] , eax reads [esp,eax] writes []
[1136745B] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[1136745C] = pushfd  reads [esp] writes [esp]
[1136745D] = pushfd  reads [esp] writes [esp]
[1136745F] = pop dword [esp+0x3C] reads [esp] writes [esp]
[11367463] = pushfd  reads [esp] writes [esp]
[11367464] = lea esp , dword [esp+0x40] reads [esp] writes [esp]
[11367468] = ja 0x1136876B reads [] writes []
[1136876B] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[1136876C] = mov dword [esp+0x1C] , ebx reads [esp,ebx] writes []
[11368770] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[11368771] = mov byte [esp] , 0xB9 reads [esp] writes []
[11368775] = lea esp , dword [esp+0x3C] reads [esp] writes [esp]
[11368779] = push esp reads [esp] writes [esp]
[1136877A] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[1136877B] = call 0x11366D7E reads [] writes [esp]
[11366D7E] = mov dword [esp+0x20] , edi reads [esp,edi] writes []
[11366D82] = mov byte [esp+0x04] , bh reads [esp,ebx] writes []
[11366D86] = call 0x11367E5F reads [] writes [esp]
[11367E5F] = push 0x01292F0F reads [esp] writes [esp]
[11367E64] = mov dword [esp+0x24] , ebp reads [esp,ebp] writes []
[11367E68] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[11367E69] = mov word [esp] , cx reads [esp,ecx] writes []
[11367E6D] = mov dword [esp+0x40] , esi reads [esp,esi] writes []
[11367E71] = push edi reads [esp,edi] writes [esp]
[11367E72] = pushfd  reads [esp] writes [esp]
[11367E73] = push dword [esp] reads [esp] writes [esp]
[11367E76] = mov dword [esp] , 0x4E582BE5 reads [esp] writes []
[11367E7D] = lea esp , dword [esp+0x4C] reads [esp] writes [esp]
[11367E81] = jmp 0x11366FB5 reads [] writes []
[11366FB5] = movzx si , cl reads [ecx] writes [esi]
[11366FB9] = pushfd  reads [esp] writes [esp]
[11366FBA] = setno bh reads [ebx] writes []
[11366FBD] = bswap si reads [] writes [esi]
[11366FC0] = xchg dword [esp] , ecx reads [esp] writes [ecx]
[11366FC3] = lea ebx , dword [0xDD95F526+ecx*4] reads [ecx] writes [ebx]
[11366FCA] = call 0x11367092 reads [] writes [esp]
[11367092] = mov dword [esp] , edx reads [esp,edx] writes []
[11367095] = lea esi , dword [0x1283F756+edx*4] reads [edx] writes [esi]
[1136709C] = call 0x113682A7 reads [] writes [esp]
[113682A7] = push dword [0x11367393] reads [esp] writes [esp]
[113682AD] = pop dword [esp] reads [esp] writes [esp]
[113682B0] = bswap di reads [] writes [edi]
[113682B3] = push 0x00000000 reads [esp] writes [esp]
[113682B8] = inc di reads [edi] writes [edi]
[113682BB] = dec bp reads [ebp] writes [ebp]
[113682BE] = movzx ebx , al reads [eax] writes [ebx]
[113682C1] = mov esi , dword [esp+0x30] reads [esp] writes [esi]
[113682C5] = inc di reads [edi] writes [edi]
[113682C8] = jmp 0x113672D1 reads [] writes []
[113672D1] = bswap bp reads [] writes [ebp]
[113672D4] = xchg ch , bh reads [ecx] writes [ecx,ebx]
[113672D6] = not esi reads [esi] writes [esi]
[113672D8] = dec bp reads [ebp] writes [ebp]
[113672DB] = dec esi reads [esi] writes [esi]
[113672DC] = clc  reads [] writes []
[113672DD] = call 0x11367539 reads [] writes [esp]
[11367539] = pop edi reads [esp] writes [esp,edi]
[1136753A] = rcr edi , cl reads [ecx,edi] writes [edi]
[1136753C] = rol esi , 0x16 reads [esi] writes [esi]
[1136753F] = sar di , cl reads [ecx,edi] writes [edi]
[11367542] = bsf bp , cx reads [ecx,ebp] writes [ebp]
[11367546] = bswap bp reads [] writes [ebp]
[11367549] = mov ebp , esp reads [esp] writes [ebp]
[1136754B] = shrd di , bx , 0x00000006 reads [ebx,edi] writes [edi]
[11367550] = xadd bx , di reads [edi] writes [ebx]
[11367554] = sar bx , 1  reads [ebx] writes [ebx]
[11367557] = xchg di , bx reads [edi] writes [ebx,edi]
[1136755A] = sub esp , 0x000000C0 reads [esp] writes [esp]
[11367560] = shl edi , cl reads [ecx,edi] writes [edi]
[11367562] = mov edi , esp reads [esp] writes [edi]
[11367564] = push 0x060102E7 reads [esp] writes [esp]
[11367569] = push ebx reads [esp,ebx] writes [esp]
[1136756A] = or ecx , ebp reads [ecx,ebp] writes [ecx]
[1136756C] = mov ebx , esi reads [esi] writes [ebx]
[1136756E] = bsr cx , cx reads [ecx] writes [ecx]
[11367572] = add ch , 0x8D reads [ecx] writes [ecx]
[11367575] = add esi , dword [ebp+0x00] reads [ebp,esi] writes [esi]
[11367578] = add esp , 0x08 reads [esp] writes [esp]
[1136757B] = or ch , bl reads [ecx,ebx] writes [ecx]
[1136757D] = neg al reads [eax] writes [eax]
[1136757F] = bswap cx reads [] writes [ecx]
[11367582] = mov al , byte [esi] reads [esi] writes [eax]
[11367584] = shrd cx , bx , cl reads [ecx,ebx] writes [ecx]
[11367588] = call 0x11366955 reads [] writes [esp]
[11366955] = clc  reads [] writes []
[11366956] = sub al , bl reads [eax,ebx] writes [eax]
[11366958] = dec cx reads [ecx] writes [ecx]
[1136695B] = mov word [esp] , 0xD95C reads [esp] writes []
[11366961] = inc esi reads [esi] writes [esi]
[11366962] = pop ecx reads [esp] writes [esp,ecx]
[11366963] = xor cl , 0x1E reads [ecx] writes [ecx]
[11366966] = sub al , 0x82 reads [eax] writes [eax]
[11366968] = rcr ch , 0x02 reads [ecx] writes [ecx]
[1136696B] = not al reads [eax] writes [eax]
[1136696D] = mov ch , dh reads [edx] writes [ecx]
[1136696F] = mov ecx , eax reads [eax] writes [ecx]
[11366971] = movzx cx , cl reads [ecx] writes [ecx]
[11366975] = call 0x11366BDC reads [] writes [esp]
[11366BDC] = rol al , 1  reads [eax] writes [eax]
[11366BDE] = sub ch , ah reads [eax,ecx] writes [ecx]
[11366BE0] = cmp cx , dx reads [ecx,edx] writes []
[11366BE3] = push 0xFDA5E80A reads [esp] writes [esp]
[11366BE8] = sub bl , al reads [eax,ebx] writes [ebx]
[11366BEA] = lea ecx , dword [edx-0x005F1551] reads [edx] writes [ecx]
[11366BF0] = movzx eax , al reads [eax] writes [eax]
[11366BF3] = not cx reads [ecx] writes [ecx]
[11366BF6] = pushfd  reads [esp] writes [esp]
[11366BF7] = movzx cx , dl reads [edx] writes [ecx]
[11366BFB] = setnp ch reads [ecx] writes []
[11366BFE] = mov ecx , dword [0x113675FD+eax*4] reads [eax] writes [ecx]
[11366C05] = mov dword [esp] , 0x9EA6662B reads [esp] writes []
[11366C0C] = pushad  reads [esp,eax,ecx,edx,ebp,ebx,esi,edi] writes [esp]
[11366C0D] = jmp 0x11368C5C reads [] writes []
[11368C5C] = dec ecx reads [ecx] writes [ecx]
[11368C5D] = cmp bl , 0x13 reads [ebx] writes []
[11368C60] = cmp ch , bl reads [ecx,ebx] writes []
[11368C62] = add ecx , 0x00000000 reads [ecx] writes [ecx]
[11368C68] = call 0x11368BDF reads [] writes [esp]
[11368BDF] = call 0x11368BF5 reads [] writes [esp]
[11368BF5] = mov dword [esp+0x30] , ecx reads [esp,ecx] writes []
[11368BF9] = pushfd  reads [esp] writes [esp]
[11368BFA] = push dword [esp+0x34] reads [esp] writes [esp]
[11368BFE] = retn 0x0038 reads [] writes [esp]

......ucTrace
[113682C1] = mov esi , dword [esp+0x30]
[113672D6] = not esi
[113672DB] = dec esi
[1136753C] = rol esi , 0x16
[1136756C] = mov ebx , esi
[11367575] = add esi , dword [ebp+0x00]
[11367582] = mov al , byte [esi]
[11366956] = sub al , bl
[11366966] = sub al , 0x82
[1136696B] = not al
[11366BDC] = rol al , 1
[11366BF0] = movzx eax , al
[11366BFE] = mov ecx , dword [0x113675FD+eax*4]
[11368C5C] = dec ecx
[11368C62] = add ecx , 0x00000000
2011-1-22 11:25
0
游客
登录 | 注册 方可回帖
返回
// // 统计代码