VMProtect1.8主程序脱壳分析NOOBY牛已经玩得差不多了我来补一刀 ^_^手中没有正式版的试炼品只好拿1.8DEMO主程序看时间比较久了忘得差不多如果分析有误请各位见谅勾上SOD全部选项载入VMPROTECT.EXE 停在TLS入口 ALT+M看到基址为00010000bp VirtualProtect+13 F9 4次后看到解码了到00011000看看FF25被弄成了什么样子VMP主程序是DELPHI写的因此只关注FF25类IAT 而不用关注 CALL [XX]和MOV EXX,XX/CALL XX这些使得针对性的IAT修复工作减少了不少体力活引用:00011278 55 push ebp00011279 E8 30C52800 call 0029D7AE ; 0029D7AE0001127E 8BC0 mov eax,eax00011280 50 push eax00011281 E8 E8E92700 call 0028FC6E ; 0028FC6E00011286 8BC0 mov eax,eax00011288 55 push ebp00011289 E8 5B333700 call 003845E9 ; 003845E90001128E 8BC0 mov eax,eax00011290 52 push edx00011291 E8 FBE02C00 call 002DF391 ; 002DF391被错位了写段脚本恢复FF25的错位引用:luanxu:inc searchfind search,#E8??????008BC0#cmp $RESULT,0je exitmov search,$RESULTGCI search,DESTINATIONcmp $RESULT,001F3000 //UPX0-VAjb luanxucmp $RESULT,003DE000 //UPX2-VAjae luanxuGCI search,COMMANDdec searchmov [search],#909090909090#asm search,$RESULTjmp luanxu修复后:引用:00011278 E8 31C52800 call 0029D7AE ; 0029D7AE0001127D 90 nop0001127E 8BC0 mov eax,eax00011280 E8 E9E92700 call 0028FC6E ; 0028FC6E00011285 90 nop00011286 8BC0 mov eax,eax00011288 E8 5C333700 call 003845E9 ; 003845E90001128D 90 nop0001128E 8BC0 mov eax,eax00011290 E8 FCE02C00 call 002DF391 ; 002DF39100011295 90 nop找个CALL跟跟看有什么新花样 EIP到00011278 单步什么都不用看只看3条引用:MOV EXX,ALEA EXX,[EXX+B]LEA EXX,[EXX+C]这个CALL里用到以下3条引用:002ADE81 BD 56720500 mov ebp,57256002ADE8A 8BAD AF693000 mov ebp,dword ptr ss:[ebp+3069AF]0034A300 8DAD 626F45AB lea ebp,dword ptr ss:[ebp+AB456F62]前面2条合起来指向一个DWORD 和最后一条组装成最终的函数地址引用:[A+B]=[57256+3069AF]=[0035DC05]=D13B2C85----记为R1R1+AB456F62=7C809BE7--指向我本机的kernel32.CloseHandle NOOBY牛的视频里找的就是这个视频里面最后生成的LOG文件里面每一行的4个成员后面2个一目了然是真实函数以及对应的DLL 前面2个则是A+B,C了这里VMP把A+B拆分成了A和B 使得我们难以在第一次看到A或者B时就能确定是哪个函数(关于NOOBY的VMP1.8脚本可能会另外撰文补充或者等NOOBY牛的BIN ^_^)经过这3条之后最终函数的真实地址保存在EXX中这里的EXX不是固定的给通用脚本编写增加不少难度最后保存在EXX中的函数会通过一个引用:push dword ptr ss:[esp+D]retn E结构返回真实API地址这里的D,E也不是固定的看完FF25后再来看看IAT调用一般的DELPHI程序第一处IAT调用CALL便是这个引用:00011430 53 push ebx00011431 83C4 BC add esp,-4400011434 BB 0A000000 mov ebx,0A00011439 54 push esp0001143A E8 260E3A00 call 003B2265 ; 003B22650001143F F64424 2C 01 test byte ptr ss:[esp+2C],100011444 74 05 je short 0001144B ; 0001144B00011446 0FB75C24 30 movzx ebx,word ptr ss:[esp+30]0001144B 8BC3 mov eax,ebx0001144D 83C4 44 add esp,4400011450 5B pop ebx00011451 C3 retn0001143A处的CALL应该指向FF25型的GetStartupInfoA 然而这里指向的地址003B2265落在UPX1段分析过程略最终知道 VMP把它和FF25型IAT用了同样的方法处理直接指向了真实函数这样使我们的修复工作变得很尴尬因为IAT 和IAT调用都通过CALL指向壳段而FF25修复后占6个字节 IAT调用CALL则只占5个字节如果不分开处理最终会覆盖后面的一字节而且VMP对于每一个函数哪怕是相同的函数都会分配不同的过程来单独处理基于避免与VM正面对抗的想法以及前面提到的种种困难和尴尬我只好用一种尴尬的方法来处理----"云断点"前面提到的每个函数会通过一个PUSH/RETN结构返回真实地址于是我选择对UPX1段所有的这种结构下断最终找到下了几百个断点是为"云断点"云断点:引用:mov fi,001F3000 //001F3000为UPX0段VAloop:inc fifind fi,#FF7424??C2??00#cmp $RESULT,0je UPX1 //继续在UPX1段寻找add $RESULT,4mov fi,$RESULTwrta sFile,fi //记录wrta sFile,"\r\n"bp fi 下断jmp loopUPX1:cmp fi,00289000//UPX1段VAjae exitmov fi,00289000 //循环jmp loopexit:ret然后记录所有IAT和IAT调用经过这种结构的返回地址并分别记录FF25型IAT 和IAT调用的地址在下断和跟踪的过程中发现有一些指向了UPX0段而代码段里被VM处理过的也会指向UPX0段为了避免与VM混淆于是我记录下所有指向UPX0段的CALL 然后手工分离出VMCALL和IAT调用CALL 这样也给后续的修复工作提供了便利所幸的是这样的IAT并不多只有十个左右记录FF25型IAT和真实函数:引用:var fivar sFilevar tmpmov sFile,"FF25.TXT"mov fi,00011000loop:inc fifind fi,#E8??????00??8BC0#//找CALL XX// XX--此处VMP随机填充的一个字节// MOV EAX,EAX结构cmp $RESULT,0je exitmov fi,$RESULTgci fi,DESTINATIONcmp $RESULT,289000jb loopcmp $RESULT,3DE000//判断目标地址是否在UPX1段jae loopwrta sFile,fi //记录IAT地址wrta sFile,"\r\n"mov eip,fiestomov tmp,[esp]wrta sFile,tmp//记录真实函数地址wrta sFile,"\r\n"jmp loop同样方法记录IAT调用及其对应函数地址记为zhizhen.txt .我的思路是这样的:1.首先修复FF252.通过FF25指向的函数地址到IAT调用CALL对应的记录文件中查找最后将对应的IAT调用的指针指向FF25型IAT.因为OLLYSCR中的REV指令对[XX]操作时,会自动过滤前面的0,只好找雪雪写了一个小工具来取反,打包在附件中。
分别对FF25.TXT全部取反,对ZHIZHEN.TXT 隔行取反,方便脚本的操作。
保存结果为FF25.BIN和ZHIZHEN.BIN。
修复FF25:引用:var tmpvar neicunvar neicun1alloc 2000mov neicun,$RESULTlm neicun,2000,"ff25.bin"mov neicun1,neicunmov tmp,[neicun+4]eval "jmp {tmp}"asm [neicun],$RESULT //修复第一个loop:add neicun,8cmp [neicun],0je exitmov tmp,[neicun+4] //+4处为真实函数地址eval "jmp {tmp}"asm [neicun],$RESULT //将原FF25CALL修复成JMP XXjmp loopexit:free neicun1,2000ret脚本运行完毕后用UIF修复直接调用为FF25 记录修复后IAT的RVA 修复IAT调用:引用:var fivar searchvar strvar neicunvar neicun1mov search,00011000alloc 8000mov neicun,$RESULTlm neicun,8000,"zhizhen.bin"//载入mov neicun1,neicunloop:mov neicun,neicun1mov str,0inc searchfind search,#FF25# //在CODE段寻找FF25类IATcmp $RESULT,0je exitmov search,$RESULTcmp [search+2],010E0000//010E0000为UIF修复后的IAT RVA jb loopcmp [search+2],010E0800//本例中IAT大小为800jae loopGCI search,DESTINATIONmov fi,$RESULTeval "#{fi}#"//真实函数地址转换成查找值mov str,$RESULTfind neicun1,str,8000//在IAT调用文件中查找相同函数cmp $RESULT,0je loopmov neicun,$RESULTsub neicun,4mov tmp,[neicun]//指针定位到对应的IAT调用eval "call {search}"asm tmp,$RESULT//将IAT调用指向真实的FF25add neicun,8//第一次修复偷懒直接写了个过程find://循环修复IAT调用find neicun,str,8000cmp $RESULT,0je loopmov neicun,$RESULTsub neicun,4mov tmp,[neicun]eval "call {search}"asm tmp,$RESULTadd neicun,8jmp findexit:ret至此IAT修复完毕找到OEP:001E4C68修复OEP:引用:001E4C68 55 push ebp001E4C69 8BEC mov ebp,esp001E4C6B 83C4 F4 add esp,-0C001E4C6E B8 A0471E00 mov eax,1E47A0001E4C73 E8 702FE3FF call 00017BE8 ; 00017BE8001E4C78 A1 84901E00 mov eax,dword ptr ds:[1E9084]001E4C7D 8B00 mov eax,dword ptr ds:[eax]001E4C7F E8 3425E8FF call 000671B8 ; 000671B8001E4C84 A1 84901E00 mov eax,dword ptr ds:[1E9084]001E4C89 8B00 mov eax,dword ptr ds:[eax]001E4C8B BA E04C1E00 mov edx,1E4CE0 ; ASCII "VMProtect"001E4C90 E8 2721E8FF call 00066DBC ; 00066DBC001E4C95 8B0D A4901E00 mov ecx,dword ptr ds:[1E90A4] ;VMProted.001ED1F0001E4C9B A1 84901E00 mov eax,dword ptr ds:[1E9084]001E4CA0 8B00 mov eax,dword ptr ds:[eax]001E4CA2 8B15 B8011800 mov edx,dword ptr ds:[1801B8] ;VMProted.00180204001E4CA8 E8 2325E8FF call 000671D0 ; 000671D0001E4CAD 8B0D B08F1E00 mov ecx,dword ptr ds:[1E8FB0] ;VMProted.001EDDC4001E4CB3 A1 84901E00 mov eax,dword ptr ds:[1E9084]001E4CB8 8B00 mov eax,dword ptr ds:[eax]001E4CBA 8B15 C02E1D00 mov edx,dword ptr ds:[1D2EC0] ;VMProted.001D2F0C001E4CC0 E8 0B25E8FF call 000671D0 ; 000671D0001E4CC5 A1 84901E00 mov eax,dword ptr ds:[1E9084]001E4CCA 8B00 mov eax,dword ptr ds:[eax]001E4CCC E8 7F25E8FF call 00067250 ; 00067250001E4CD1 E8 76F2E2FF call 00013F4C ; 00013F4C001E4CD6 0000 add byte ptr ds:[eax],al001E4CD8 FFFF ??? ; Unknown command001E4CDA FFFF ??? ; Unknown command001E4CDC 0900 or dword ptr ds:[eax],eax001E4CDE 0000 add byte ptr ds:[eax],al001E4CE0 56 push esi001E4CE1 4D dec ebp001E4CE2 50 push eax001E4CE3 72 6F jb short 001E4D54 ; 001E4D54001E4CE5 74 65 je short 001E4D4C ; 001E4D4C001E4CE7 637400 00 arpl word ptr ds:[eax+eax],si001E4CEB 0000 add byte ptr ds:[eax],al修复几处VM:引用:00017BE8 50 push eax00017BE9 6A 00 push 000017BEB E8 F8FEFFFF call 00017AE8 ; 00017AE800017BF0 BA 08511E00 mov edx,1E510800017BF5 52 push edx00017BF6 8905 DCA41E00 mov dword ptr ds:[1EA4DC],eax00017BFC 8942 04 mov dword ptr ds:[edx+4],eax00017BFF C742 08 0000000>mov dword ptr ds:[edx+8],000017C06 C742 0C 0000000>mov dword ptr ds:[edx+C],000017C0D E8 8AFFFFFF call 00017B9C ; 00017B9C00017C12 5A pop edx00017C13 58 pop eax00017C14 E8 27C2FFFF call 00013E40 ; 00013E4000017C19 C3 retn引用:00013E40 8905 ACA41E00 mov dword ptr ds:[1EA4AC],eax00013E46 31C0 xor eax,eax00013E48 8905 B0A41E00 mov dword ptr ds:[1EA4B0],eax00013E4E 8915 B4A41E00 mov dword ptr ds:[1EA4B4],edx00013E54 8B42 04 mov eax,dword ptr ds:[edx+4]00013E57 8905 20A01E00 mov dword ptr ds:[1EA020],eax00013E5D E8 D6FEFFFF call 00013D38 ; 00013D3800013E62 C605 28A01E00 0>mov byte ptr ds:[1EA028],000013E69 E8 72FFFFFF call 00013DE0 ; 00013DE000013E6E C3 retn引用:00017B9C 53 push ebx00017B9D 81C4 F8FEFFFF add esp,-10800017BA3 68 05010000 push 10500017BA8 8D4424 04 lea eax,dword ptr ss:[esp+4]00017BAC 50 push eax00017BAD A1 DCA41E00 mov eax,dword ptr ds:[1EA4DC]00017BB2 50 push eax00017BB3 E8 28FFFFFF call 00017AE0 ; 00017AE000017BB8 8BC4 mov eax,esp00017BBA E8 C5EDFFFF call 00016984 ; 0001698400017BBF 8BD8 mov ebx,eax00017BC1 891D 18511E00 mov dword ptr ds:[1E5118],ebx00017BC7 85DB test ebx,ebx00017BC9 75 0A jnz short 00017BD5 ; 00017BD500017BCB A1 0C511E00 mov eax,dword ptr ds:[1E510C]00017BD0 A3 18511E00 mov dword ptr ds:[1E5118],eax00017BD5 B8 08511E00 mov eax,1E510800017BDA E8 BDF0FFFF call 00016C9C ; 00016C9C00017BDF 81C4 08010000 add esp,10800017BE5 5B pop ebx00017BE6 C3 retn引用:001A5E44 55 push ebp001A5E45 8BEC mov ebp,esp001A5E47 33C9 xor ecx,ecx001A5E49 51 push ecx001A5E4A 51 push ecx001A5E4B 51 push ecx001A5E4C 51 push ecx001A5E4D 53 push ebx001A5E4E 8BD8 mov ebx,eax001A5E50 33C0 xor eax,eax001A5E52 55 push ebp001A5E53 68 E25F1A00 push 1A5FE2001A5E58 64:FF30 push dword ptr fs:[eax]001A5E5B 64:8920 mov dword ptr fs:[eax],esp001A5E5E 8D55 FC lea edx,dword ptr ss:[ebp-4]001A5E61 8B43 58 mov eax,dword ptr ds:[ebx+58]001A5E64 E8 1F8CE8FF call 0002EA88 ; 0002EA88001A5E69 8B55 FC mov edx,dword ptr ss:[ebp-4]001A5E6C 8B83 FC020000 mov eax,dword ptr ds:[ebx+2FC]001A5E72 8B40 58 mov eax,dword ptr ds:[eax+58]001A5E75 E8 268CE8FF call 0002EAA0 ; 0002EAA0001A5E7A 8B15 30921E00 mov edx,dword ptr ds:[1E9230] ;VMProted.001ECBB4001A5E80 8B92 94000000 mov edx,dword ptr ds:[edx+94]001A5E86 8BC3 mov eax,ebx001A5E88 E8 E716EAFF call 00047574 ; 00047574001A5E8D 8B15 30921E00 mov edx,dword ptr ds:[1E9230] ;VMProted.001ECBB4001A5E93 8B92 68010000 mov edx,dword ptr ds:[edx+168]001A5E99 8B83 E8020000 mov eax,dword ptr ds:[ebx+2E8]001A5E9F E8 D016EAFF call 00047574 ; 00047574001A5EA4 BA 885F1A00 mov edx,1A5F88 ; ASCII "VMProtectProfessional v 1.8 [demo]"//省略部分详见附件脚本DUMP-FIX运行DUMP_.EXE 正常运行发现界面上的选项全部都成了乱码无奈对照NOOBY 牛的1.7版修复以下过程引用:001D607C 55 push ebp001D607D 8BEC mov ebp,esp001D607F 81C4 8CFEFFFF add esp,-174001D6085 53 push ebx001D6086 56 push esi001D6087 57 push edi001D6088 33C9 xor ecx,ecx001D608A 898D 8CFEFFFF mov dword ptr ss:[ebp-174],ecx001D6090 894D FC mov dword ptr ss:[ebp-4],ecx001D6093 894D F8 mov dword ptr ss:[ebp-8],ecx001D6096 8BD8 mov ebx,eax001D6098 BF C8DD1E00 mov edi,1EDDC8001D609D 33C0 xor eax,eax001D609F 55 push ebp001D60A0 68 06661D00 push 1D6606001D60A5 64:FF30 push dword ptr fs:[eax]001D60A8 64:8920 mov dword ptr fs:[eax],esp001D60AB BA 1C661D00 mov edx,1D661C ; ASCII "VMProtectProfessional v 1.8 [demo]"//省略部分详见附件脚本此过程将近600字节膜拜一下生猛的NOOBY 我对照1.7修复都花了近2个小时人肉的力量啊~~~剩下几个VM过程没有处理 CPUID? 补区? 水平和精力有限见谅 ^_^捣鼓一番后没有乱码了不过加壳的时候提示出错不再看了等儿童节怕文章写得太乱录了段视频抛砖引玉期待简单的处理方法引用:衷心感谢雪落的瞬间 NOOBY GOLDSUN A_P 啊cr fly 海风月影cyto Κūйɡβǐм等众位朋友在我学习过程中给予的无私帮助与支持.^_^Kissy/。