个人总结的一个VMP脱壳步骤
- 格式:doc
- 大小:35.50 KB
- 文档页数:5
脱壳基本知识在一些计算机软件里有一段专门负责保护软件不被非法修改或反编译的程序。
它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。
以下是由店铺整理关于脱壳知识的内容,希望大家喜欢!壳的概念从技术的角度出发,壳是一段执行于原始程序前的代码。
原始程序的代码在加壳[1] 的过程中可能被压缩、加密……。
当加壳后的文件执行时,壳-这段代码先于原始程序运行,他把压缩、加密后的代码还原成原始程序代码,然后再把执行权交还给原始代码。
软件的壳分为加密壳、压缩壳、伪装壳、多层壳等类,目的都是为了隐藏程序真正的OEP(入口点,防止被破解)。
作者编好软件后,编译成exe可执行文件。
1.有一些版权信息需要保护起来,不想让别人随便改动,如作者的姓名,即为了保护软件不被破解,通常都是采用加壳来进行保护。
2.需要把程序搞的小一点,从而方便使用。
于是,需要用到一些软件,它们能将exe可执行文件压缩,3.在黑客界给木马等软件加壳脱壳以躲避杀毒软件。
实现上述功能,这些软件称为加壳软件。
脱壳软件加壳一般属于软件加密,越来越多的软件经过压缩处理,给汉化带来许多不便,软件汉化爱好者也不得不学习掌握这种技能。
脱壳一般分手动和自动两种,手动就是用TRW2000、TR、SOFTICE等调试工具对付,对脱壳者有一定水平要求,涉及到很多汇编语言和软件调试方面的知识。
而自动就是用专门的脱壳工具来脱,最常用某种压缩软件都有他人写的反压缩工具对应,有些压缩工具自身能解压,如UPX;有些不提供这功能,如:ASPACK,就需要UNASPACK对付,好处是简单,缺点是版本更新了就没用了。
另外脱壳就是用专门的脱壳工具来对付,最流行的是PROCDUMP v1.62 ,可对付各种压缩软件的压缩档。
在这里介绍的是一些通用的方法和工具,希望对大家有帮助。
我们知道文件的加密方式,就可以使用不同的工具、不同的方法进行脱壳。
下面是我们常常会碰到的加壳方式及简单的脱壳措施,供大家参考:脱壳的基本原则就是单步跟踪,只能往前,不能往后。
脱壳机操作流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!脱壳机操作流程脱壳机是一种常用的电子产品维修工具,主要用于打开封装后的电子元器件,便于维修和更换。
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,只好找雪雪写了一个小工具来取反,打包在附件中。
vmp脱壳还原代码
VMProtect 是一款反调试、加壳保护软件,具有高度的安全性。
可以将程序进行加密,增加程序的难度,从而使得攻击者在破解时更难达到目的。
VMProtect脱壳还原代码就是通过脱去VMProtect壳来恢复原始的程序代码。
一般情况下,脱壳的流程如下:
1. 首先,使用反编译工具,将程序反编译成可读的
C/C++语言代码;
2. 然后,研究反编译出来的代码,找到VMProtect壳的特征和加壳方式;
3. 最后,根据VMProtect壳的特征和加壳方式,编写脱壳程序,将VMProtect壳去掉,还原原始的程序代码;
4. 最后,将还原后的程序代码重新编译,生成程序可执行文件。
[原创]手工脱壳实例演示适合读者:破解爱好者、程序员前置知识:汇编语言阅读能力,基本破解工具的使用方法手工脱壳实例演示文/图 wast我们通常在汉化软件和解密软件的时候都需要脱壳,因为大部分的软件都有加壳。
“壳”是一段专门负责保护软件不被非法修改或反编译的程序。
它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。
经过加壳的软件在跟踪时已无法看到其真实的十六进制代码,因此可以起到保护软件的目的。
给软件加壳的主要目的有两点:第一就是达到压缩EXE文件的目的,现在虽然说硬盘的容量已经很大了,但是程序“减肥”还是一个很好的节约空间的办法,还有就是方便网络传输;其二就是加密目的,有一些版权信息需要保护起来,不能让别人随意更改,如作者的姓名、软件的名称等。
大部分的程序加壳是为了防止反跟踪,防止程序被人跟踪调试,防止程序算法被别人静态分析。
给软件加壳的实质,其实就是给可执行文件加上个外衣。
用户执行的只是这个外壳程序,也就是当你执行这个程序的时候这个壳就会把原来的程序在内存中解开,解开后的工作就交给真正的程序了。
所以,所有的工作都是在内存中进行的,而用户是无法知道程序具体是怎么样在内存中运行的。
正是出于保护自己的软件的目的,许多软件都给自己披上了一层坚固的“壳”,使我们无法直接找到其中的资源,如果要汉化这样的软件,就必须给它脱壳,如果不给它脱壳,则无法完成汉化工作。
可以这样说,如果你想汉化软件,却不会脱壳的话,那将寸步难行!所以我们很有必要了解加壳/脱壳技术。
常用加壳软件及其特点为了加密,会用到一些软件。
它们能将可执行文件压缩和对信息加密,实现“壳”的两个功能,这类软件称为加壳软件。
在软件上加上的东东也就是我们讨论的“壳”了。
但是有一点大家得搞明白就是加壳软件是不同于一般的Winzip、Winrar等压缩软件的,加了壳后的文件能够直接运行,也就是加壳后还是一个可执行文件,它们的解压在内存中完成;Winzip等软件只能是把文件解压到硬盘中,只是将压缩后的文件还原成原文件。
Virbox Protector 是一种用于保护软件安全的工具,它可以对本地程序进行多种方式的保护,包括代码混淆、代码虚拟化、代码加密等。
如果Virbox Protector对某个程序进行了保护,那么该程序可能具有一些防止被反编译或脱壳的机制。
然而,Virbox Protector 的具体脱壳方法因程序的具体保护方式和版本而异。
如果需要针对某个具体的 Virbox Protector 保护的程序进行脱壳,可以尝试以下方法:
1. 静态分析:对程序的代码或数据段进行整体解压缩和解密,然后进行反编译和静态分析,以理解程序的逻辑和功能。
这需要一定的逆向工程知识和技能。
2. 动态调试:使用调试器对程序进行动态调试,单步跟踪程序的执行流程,理解程序的逻辑和行为。
这需要一定的调试技巧和经验。
3. 寻找漏洞:寻找程序中的漏洞或弱点,例如未授权访问、输入验证不严格等,利用这些漏洞来绕过保护机制,从而获取程序的源代码或可执行文件。
这需要较高的安全知识和技能,并可能涉及到违法行为。
需要注意的是,无论采用哪种方法,破解或绕过Virbox Protector 的保护都需要一定的技术水平和专业知识,并且可
能存在法律风险。
因此,建议遵守法律法规和道德规范,不要进行非法的软件破解和反编译活动。
手动脱壳简简单单在我们进行逆向分析的时候,通常会遇到有些文件被加密处理过,也就是我们通常所说的被加了壳,这时他的内部结构都已经改变,我们想要继续分析是很麻烦的,所以我们需要把它从壳中分离出来,也就是我们常说的脱壳。
现在越来越多的软件都使用了加壳的保护方法,所以脱壳是我们在逆向分析过程中很主要的步骤,掌握它至关重要壳是最早出现的一种专业加密软件。
不同的壳的侧重点也不同,有的侧重于压缩,有的侧重于加密,所以出现了压缩壳和加密壳。
压缩壳的特点是减小软件的体积,我们常见的有:UPX,ASPack,PECompack等。
加密壳的则侧重于加密,保护强度较大,常见的有:ASProtect,Armadillo,Themida等。
第一步寻找OEP★OEP(Original Entry Point):程序的原入口点,就是壳程序在完成了对原程序的还原后,开始跳转到刚还原的程序执行,此时的地址就是入口点的值。
1 单步跟踪首先,我们运行peid, 将我们要检测的程序拖到上面,可以看到它是用aspack加的壳,如图1。
我们运行OD,点击菜单栏中的“文件”→“打开”,把我们需要脱壳的文件加载进来,接着就会弹出一个对话框“模块……你仍要继续分析吗”,如图2,我们选择“否”(不管什么方法脱壳都要按“否”),程序就会停以下的代码处:01013001 > 90 nop01013002 60 pushad01013003 E8 03000000 call 0101300B01013008 - E9 EB045D45 jmp 465E34F80101300D 55 push ebp0101300E C3 retn0101300F E8 01000000 call 0101301501013014 EB 5D jmp short 01013073我们按F8来跟踪一下,当到了call 0101300B这里的时候,记事本自己打开了,我们按Ctrl+F2重新载入文件,再来跟踪,当我们再次遇到call 0101300B这一句的时候我们按F7跟进,代码会来到这里:0101300B 5D pop ebp0101300C 45 inc ebp0101300D 55 push ebp0101300E C3 retn我们继续F8来跟踪,当到了retn一句时,程序返回了,停在了call的下面一句jmp465E34F8上,跳转以后代码来到了下面的这一句call 01013015,继续F8,如果遇到程序往回跳,那么我们就在下一句代码处按F4,这样跟踪一段时间以后,我们会看到这样的代码:010133BB 68 9D730001 push 0100739D010133C0 C3 retn再F8一下我们的程序就返回了了这里:0100739D 6A 70 push 700100739F 68 98180001 push 01001898010073A4 E8 BF010000 call 01007568到这里,我们就已经到达OEP,单步跟踪法测试成功。
第一步:bp VirtualProtect按F9 运行直到栈出现:PAGE_READONL Y 如图:第二步:到代码段下内在访问断点如图:F9 断下后,删除内在断点:如图然后单步F7往下:直到看见一个JNZ ,JMP连在一起,运行到JNZ后,在JMP处下一个F2断点,F9运行,断下后自效验完了,要删除这个断点,再去代码段下一个内在访问断点,F9运行,就到OEP了,册除内存断点把OEP记下,要配置用的如图:配置脚本:Mov first, 这里填OEP所以到OEP了以后要记录它的地址接下来F7单步往下找第二个要填写的地址,一直F7过几JMP长跳后会到这里:如图:0046617A - 0F84 495CFFFF JE delphi7?0045BDC9这句很有特点,但我们要记录的是这句:00466171 BD 92E94300 MOV EBP,delphi7?0043E992记录完F7几次继续往下就到这里:这里我们要记录一句:0045BDCE 8BAD 42850100 MOV EBP,DWORD PTR SS:[EBP+18542]然后F7单步到第一句后看信息窗口见:在信息窗口对准:EDAE30E1 右键选在数据窗口中跟随,然后下第一个字节的硬件写入断点如图:F7到这一句:0045BDDB 8DAD 6086D28E LEA EBP,DWORD PTR SS:[EBP+8ED28660] 并记录下来,这些都是填充的地址接下来,重载,然后ctr+G去下这个函数:VirtualProtect断点,如图:F9几次好象是8次左右,这时看堆栈:刚才这里有VirtualProtect的调用过程,但现在没有了,说明到了解压的地方了,再F9一次,然后,鼠标往上翻一下看见下图:这里是填充的地方了记录这一句:004B5B72 8910 MOV DWORD PTR DS:[EAX],EDX它的地址就是脚本要填的第二个配置项了:Mov write , 004B5B72接下来找getAP脚本第三项:我们在这句:004B5B72 8910 MOV DWORD PTR DS:[EAX],EDX下断,然后删除硬件断点和函数点,F9四次到信息窗口如下图:打开执行:open run tract, 再执行:tract into , 然后F9两次断下后,打开View,执行:run tract 查看记录,然后右键执行:Log to file ,打开如图:注意:上面的钩要选完才行执行:打开铵钮,再右键:执行:close log file,然后,去debug菜单执行:close run tract, 然后关闭记录窗口,可以查看记录文件了。
WinlicenseWinlicenseBy VirusWizard今天第一次接触Themida/Winlicense,基本上都是脚本,算不上什么技术,但作为实验,记录一下。
总体流程:使用Nooby的脚本跑到FakeOEP,然后修复StolenCode。
首先使用Winlicense然后调整脚本中的Base记事本的WinLicen的Base。
我这里的Base是01015000,所以对应的代码修改成:mov tmdbase, 01015000接下来用StrongOD,选项全部勾上,开始跑脚本。
跑完脚本之后,来到这里:01007568 68 BA750001 push 010075BA0100756D 64:A1 00000000 mov eax, dword ptr fs:[0]01007573 50 push eax01007574 8B4424 10 mov eax, dword ptr [esp+10]01007578 896C24 10 mov dword ptr [esp+10], ebp0100757C 8D6C24 10 lea ebp, dword ptr [esp+10]01007580 2BE0 sub esp, eax01007582 53 push ebx01007583 56 push esi01007584 57 push edi01007585 8B45 F8 mov eax, dword ptr [ebp-8]01007588 8965 E8 mov dword ptr [ebp-18], esp0100758B 50 push eax0100758C 8B45 FC mov eax, dword ptr [ebp-4]0100758F C745 FC FFFFFFF>mov dword ptr [ebp-4], -101007596 8945 F8 mov dword ptr [ebp-8], eax01007599 8D45 F0 lea eax, dword ptr [ebp-10]0100759C 64:A3 00000000 mov dword ptr fs:[0], eax010075A2 C3 retn观察堆栈,发现这个:0006FF8C 011ABF9B NOTEPAD_.011ABF9B0006FF90 01001898 NOTEPAD_.010018980006FF94 0000007070有些眼熟,用OD打开原记事本,看到头两行:0100739D > $ 6A 70 push 70 ; (initial cpu selection) 0100739F . 68 push 01001898然后F4到011ABF9B,这个时候会进入VM,我暂时还没那技术去分析。
WinlicenseWinlicenseBy VirusWizard今天第一次接触Themida/Winlicense,基本上都是脚本,算不上什么技术,但作为实验,记录一下。
总体流程:使用Nooby的脚本跑到FakeOEP,然后修复StolenCode。
首先使用Winlicense然后调整脚本中的Base记事本的WinLicen的Base。
我这里的Base是01015000,所以对应的代码修改成:mov tmdbase, 01015000接下来用StrongOD,选项全部勾上,开始跑脚本。
跑完脚本之后,来到这里:01007568 68 BA750001 push 010075BA0100756D 64:A1 00000000 mov eax, dword ptr fs:[0]01007573 50 push eax01007574 8B4424 10 mov eax, dword ptr [esp+10]01007578 896C24 10 mov dword ptr [esp+10], ebp0100757C 8D6C24 10 lea ebp, dword ptr [esp+10]01007580 2BE0 sub esp, eax01007582 53 push ebx01007583 56 push esi01007584 57 push edi01007585 8B45 F8 mov eax, dword ptr [ebp-8]01007588 8965 E8 mov dword ptr [ebp-18], esp0100758B 50 push eax0100758C 8B45 FC mov eax, dword ptr [ebp-4]0100758F C745 FC FFFFFFF>mov dword ptr [ebp-4], -101007596 8945 F8 mov dword ptr [ebp-8], eax01007599 8D45 F0 lea eax, dword ptr [ebp-10]0100759C 64:A3 00000000 mov dword ptr fs:[0], eax010075A2 C3 retn观察堆栈,发现这个:0006FF8C 011ABF9B NOTEPAD_.011ABF9B0006FF90 01001898 NOTEPAD_.010018980006FF94 0000007070有些眼熟,用OD打开原记事本,看到头两行:0100739D > $ 6A 70 push 70 ; (initial cpu selection) 0100739F . 68 push 01001898然后F4到011ABF9B,这个时候会进入VM,我暂时还没那技术去分析。
vmp脱壳原理
VMP(Virtual Machine Protect)是一种常用的自动化脱壳工具,它的脱壳原理主要包括以下几个步骤:
1. 扫描程序:VMP会首先扫描目标程序,识别出其中使用了VMP保护的代码片段。
VMP保护的代码片段通常被加密或者
混淆,以防止被逆向分析。
2. 反混淆解密:VMP会对识别出的代码片段进行反混淆解密
操作,还原出原始的指令。
这通常需要分析VMP的加密算法
和混淆策略,以便正确解密代码。
3. 修复指令和数据:VMP会根据解密后的代码修复虚拟指令
和数据。
VMP通常会将原始的指令和数据转化为虚拟指令和
数据,并将其存储在一个虚拟指令内存区域中。
因此,脱壳过程需要根据虚拟指令的执行顺序,将其转化为正确的指令和数据。
4. 脱壳:通过分析脱壳程序的执行流程,脱壳工具可以将脱壳程序的内存区域中的数据还原为原始的可执行文件。
通常,脱壳工具会在特定的位置设置断点,当程序执行到该位置时,保存内存中的数据到硬盘中。
5. 修复重定位:由于脱壳过程中改变了程序的内存布局,因此还需要修复程序的重定位信息,以确保程序能够正确执行。
总的来说,VMP的脱壳原理是通过识别、解密和修复VMP保
护的代码片段,最终将脱壳程序的内存区域还原为原始的可执行文件。
这一过程需要对VMP的保护机制和加密算法进行分析和破解。
一种通过后端编译优化脱虚拟机壳的方法说实话通过后端编译优化脱虚拟机壳这事儿,我一开始也是瞎摸索。
我试过好多方法啊,最早的时候,我就想着从虚拟机壳的运行原理下手,感觉只要能干扰它的正常运行就能脱壳。
我就胡乱改一些配置,就像在一个精密的机器上瞎拧螺丝一样,结果可想而知,根本没一点门道,程序还被我搞崩溃了好几次。
后来我就想,得从编译这个源头找思路。
我知道编译的时候它会对代码做很多处理,那要是能在这个过程中把虚拟机壳相关的东西优化掉,说不定就能脱壳。
那这编译的过程我得一点点研究啊。
就好比是了解一个复杂的烹饪流程,一道菜的步骤我得全知道,这编译也是,每个环节我都得去看。
然后我发现其中有些编译选项可能会影响到虚拟机壳的附着。
不过这可得小心,就像你在调配化学试剂,稍微错一点可能就满盘皆输。
比如我调整了一个跟内存分配优化相关的编译选项,我当时觉得这个可能会跟虚拟机壳在内存里的布局有冲突,也许能把壳从程序的运行态里挤出去。
我小心翼翼地改了,再看程序的运行状态。
结果还真有点变化,部分壳的功能好像有那么点不稳定,但是并没有完全脱掉。
这时候我就得总结经验,我想肯定是我调整的还不够彻底或者还得配合其他编译选项一起调整。
有一次我同时调整了好几个编译选项,涉及到代码优化、动态链接库加载方式等等这些方面。
我当时紧张死了,就像给一颗定时炸弹拆弹一样,手抖着改完。
一运行程序,居然成功了不少,虚拟机壳已经对程序的影响变得特别小。
但是这个时候还要小心,因为程序虽然能运行,但是可能会有些隐藏的问题,像是运行速度突然变慢或者某个功能有小的出错。
后来我就知道了,在做这种通过后端编译优化脱虚拟机壳的事,肯定得一点一点来。
每次改变一个编译选项就要细细观察程序运行的变化。
而且千万别贪心,一次性改太多参数,那失败的可能性极大。
而且在每一步过程中做好记录非常重要,就像你走迷宫一样,要是不留下标记,很容易就迷失方向重来。
我就因为没记录,有时候重复了之前失败的操作都不清楚。
个人总结的一个VMP脱壳步骤个人总结的一个VMP脱壳步骤个人在学习脱VMP加壳的过程中总结的一个步骤。
按照这个步骤,包括VMP1.6—2.0在内应该有70%-80%能脱壳。
脱不了的也别问我,我也刚开始学习。
我还想找人问呢。
想要脱VMP的壳,首要工作当然是要找一个强OD啦!至于是什么版本的OD自己多试验几个,网上大把大把的,一般来说只要加载了你想脱的VMP加壳程序不关闭都可以。
其次就是StrongOD.dll这个插件了,现在用的比较多的就是海风月影,同样网上也是大把大把的。
下载回来后复制到你的OD程序所在的文件夹里面的plugin里。
StrongOD的设置选项搞不懂就全部打钩。
接下来要做的工作就是搞清楚我们要脱壳的程序编程的语言了,可以用PEID或者fastscanner查看,如果在这里看不到也可以在OD载入以后通过里面的字符串判断了。
例如VB的程序会出现MSVB----/VC的会出现MSVC---等等。
这些都是程序运行所需要的windows链接文件。
做完这些预备工作接下来当然是用OD载入文件啦。
文件载入后在反汇编窗口CTRL+G搜索VirtualProtect(注意V跟P要大写,至于为什么要搜索这个别问我)。
一般来说搜索的结果会出现以下的类似:7C801AE3 E8 75FFFFFF call kernel32.VirtualProtectEx我们在这里下F2断点。
然后F9运行到我们下的这个断点。
接下来我们就要注意观察堆栈窗口了。
一般来说当我们F9运行到我们上面下的断点的时候在堆栈窗口会出现以下类似:0012F66C 00401000 |Address = TradeCen.004010000012F670 000280D1 |Size = 280D1 (164049.)0012F674 00000004 |NewProtect = PAGE_READWRITE0012F678 0012FF98 \pOldProtect = 0012FF98我们要注意观察的就是在接下来我们F9运行的时候,ADDRESS和NEWPROTECT这两行的变化。
按F9-速度别太快,直到NewProtect项变为PAGE_READONLY,这时候程序就释放完毕了。
0012F66C 0042A000 |Address = TradeCen.0042A0000012F670 000069DE |Size = 69DE (27102.)0012F674 00000002 |NewProtect = PAGE_READONLY0012F678 0012FF98 \pOldProtect = 0012FF98现在可以取消刚才我们下的断点了。
接下来就是找OEP了。
找OEP的时候我个人的一个经验就是OEP 一般就在接近上面的ADDRESS地址的附近。
例如上面的地址是0042A000,我一般就在这个基础上减到420000搜索程序的特征段,当然我们也可以直接跳到401000开始搜索。
虽然我们搜索的范围比较大,但是因为我们搜索的是命令序列,所以工作量还不是很大。
废话不多说,CTRL+G--上面的地址,然后CTRL+S 查找命令序列。
命令序列的内容就是我们用查到的编程语言的特征段。
我们可以在特征段里面选择两三句固定不变的命令查找。
例如VC++6.0的特征段是0046C07B U> 55 push ebp0046C07C 8BEC mov ebp,esp0046C07E 6A FF push -10046C080 68 18064C00 push UltraSna.004C06180046C085 68 F8364700 push UltraSna.004736F80046C08A 64:A1 00000000 mov eax,dword ptr fs:[0]0046C090 50 push eax0046C091 64:8925 00000000 mov dword ptr fs:[0],esp0046C098 83EC 58 sub esp,580046C09B 53 push ebx0046C09C 56 push esi0046C09D 57 push edi我们可以只搜索前三条命令。
找到符合前三条命令的,我们在对照接下来的命令。
只要命令相符那这个地址八九不离十就是OEP了。
如果在ADDRESS地址附近找不到OEP,那就只好用笨办法,从401000开始找吧。
找到OEP地址后,我们在OEP处点鼠标右键《此处为新EIP》。
接下来就可以dump啦。
通常选择OD 的dump插件脱壳要好点,用loadpe脱壳后要么程序不运行要么干脆没脱。
用OD的dump插件脱壳的时候,脱壳窗口下面的(重建输入表)项前面的勾一定要去掉,这个也是前辈总结的经验。
到此脱壳就结束了。
可以试验一下脱壳后的程序了。
能运行说明它在70-80%的范围,不能运行的话那也是我还在学习的内容,大家共同探讨!以下是主要几种编程语言的OEP特征段:Borland C++0040163C B> /EB 10 jmp short Borland_.0040164E0040163E |66:623A bound di,dword ptr ds:[edx]00401641 |43 inc ebx00401642 |2B2B sub ebp,dword ptr ds:[ebx]00401644 |48 dec eax00401645 |4F dec edi00401646 |4F dec edi00401647 |4B dec ebx00401648 |90 nop00401649 -|E9 98E04E00 jmp SHELL32.008EF6E60040164E \A1 8BE04E00 mov eax,dword ptr ds:[4EE08B]00401653 C1E0 02 shl eax,200401656 A3 8FE04E00 mov dword ptr ds:[4EE08F],eax0040165B 52 push edx0040165C 6A 00 push 00040165E E8 DFBC0E00 call <jmp.&KERNEL32.GetModuleHandleA>********************************************************************************** Delphi00458650 D> 55 push ebp00458651 8BEC mov ebp,esp00458653 83C4 F0 add esp,-1000458656 B8 70844500 mov eax,Delphi.004584700045865B E8 00D6FAFF call Delphi.00405C6000458660 A1 58A14500 mov eax,dword ptr ds:[45A158]00458665 8B00 mov eax,dword ptr ds:[eax]00458667 E8 E0E1FFFF call Delphi.0045684C0045866C A1 58A14500 mov eax,dword ptr ds:[45A158]00458671 8B00 mov eax,dword ptr ds:[eax]00458673 BA B0864500 mov edx,Delphi.004586B000458678 E8 DFDDFFFF call Delphi.0045645C0045867D 8B0D 48A24500 mov ecx,dword ptr ds:[45A248] ; Delphi.0045BC00 00458683 A1 58A14500 mov eax,dword ptr ds:[45A158]00458688 8B00 mov eax,dword ptr ds:[eax]0045868A 8B15 EC7D4500 mov edx,dword ptr ds:[457DEC] ; Delphi.00457E38 00458690 E8 CFE1FFFF call Delphi.0045686400458695 A1 58A14500 mov eax,dword ptr ds:[45A158]0045869A 8B00 mov eax,dword ptr ds:[eax]0045869C E8 43E2FFFF call Delphi.004568E4********************************************************************************** Visual C++ 6.00046C07B U> 55 push ebp0046C07C 8BEC mov ebp,esp0046C07E 6A FF push -10046C080 68 18064C00 push UltraSna.004C06180046C085 68 F8364700 push UltraSna.004736F80046C08A 64:A1 00000000 mov eax,dword ptr fs:[0]0046C090 50 push eax0046C091 64:8925 00000000 mov dword ptr fs:[0],esp0046C098 83EC 58 sub esp,580046C09B 53 push ebx0046C09C 56 push esi0046C09D 57 push edi0046C09E 8965 E8 mov dword ptr ss:[ebp-18],esp0046C0A1 FF15 74824A00 call dword ptr ds:[<&KERNEL32.GetVersion>] ; kernel32.GetVersion 0046C0A7 33D2 xor edx,edx0046C0A9 8AD4 mov dl,ah0046C0AB 8915 403F4F00 mov dword ptr ds:[4F3F40],edx0046C0B1 8BC8 mov ecx,eax0046C0B3 81E1 FF000000 and ecx,0FF0046C0B9 890D 3C3F4F00 mov dword ptr ds:[4F3F3C],ecx********************************************************************************** Visual C++ 7.00100739D > $ 6A 70 push 0x700100739F . 68 98180001 push NOTEPAD.01001898010073A4 . E8 BF010000 call NOTEPAD.01007568010073A9 . 33DB xor ebx,ebx**********************************************************************************汇编00401000 汇> 6A 00 push 000401002 E8 C50A0000 call <jmp.&KERNEL32.GetModuleHandleA>00401007 A3 0C354000 mov dword ptr ds:[40350C],eax0040100C E8 B50A0000 call <jmp.&KERNEL32.GetCommandLineA>00401011 A3 10354000 mov dword ptr ds:[403510],eax00401016 6A 0A push 0A00401018 FF35 10354000 push dword ptr ds:[403510]0040101E 6A 00 push 000401020 FF35 0C354000 push dword ptr ds:[40350C]00401026 E8 06000000 call 汇编.004010310040102B 50 push eax0040102C E8 8F0A0000 call <jmp.&KERNEL32.ExitProcess>00401031 55 push ebp00401032 8BEC mov ebp,esp00401034 83C4 B0 add esp,-5000401037 C745 D0 30000000 mov dword ptr ss:[ebp-30],300040103E C745 D4 0B000000 mov dword ptr ss:[ebp-2C],0B00401045 C745 D8 37114000 mov dword ptr ss:[ebp-28],汇编.00401137**********************************************************************************VB0040116C V>/$ 68 147C4000 push VB.00407C14 00401171 |. E8 F0FFFFFF call <jmp.&MSVBVM60.#100> 00401176 |. 0000 add byte ptr ds:[eax],al 00401178 |. 0000 add byte ptr ds:[eax],al0040117A |. 0000 add byte ptr ds:[eax],al0040117C |. 3000 xor byte ptr ds:[eax],al。