X86逆向14:常见的脱壳手法
本章节内容将介绍软件的脱壳技术。什么是加壳?加壳就是用来压缩或者保护软件不被非法修改破解的一种工具,而脱壳就是将已经加壳的程序从壳中剥离出来,既然能给程序进行加壳,那也就会有相应的脱壳方法,本节课我们将讲解几种常见的脱壳方法,让你能够应对一部分软件的加壳保护。
压缩壳:upx ,aspack ,fsg ,pecompach
加密壳:ASProtect ,Armadillo(穿山甲),EXEcryptor,Themida,ZProtect
虚拟机壳:VMProtect
接下来我们将使用不同的方法来脱几个常见的壳(UPX,Aspack,FSG,PECompact)
————————————————————
本章难度:★★☆☆☆☆☆☆☆☆
课程课件:CM_14.zip
————————————————————
ESP定律脱壳法
ESP定律可谓是脱壳界一大利器,该方法是由国外的一名大牛发现的。你只需学会这个ESP定律,就可以很方便的脱掉市面上大部分的压缩壳,可谓是本世纪破解界最伟大的发现。
ESP定律原理就是会将加壳过程执行一遍之后跳到OEP来执行源程序,当我们找到了OEP的时候就是找到了源程序,即可实现脱壳。
1.首先我们使用OD载入附件中的【Aspack.exe】程序,然后会看到以下代码,第一条指令是Pushad,发现第一条命令是它,就能使用ESP定律搞。
如上图,默认的如果被调试程序被加密了,OD在运行时就会弹出这个提示框,这里点是点否都可以,我就点否了节约时间。
2.接着我们按一下【F8】单步执行一次,会发现右侧寄存器窗口,只有ESP寄存器变成了红色。
3.在ESP寄存器上面按下【右键】选择,【数据窗口中跟随】,立即数。
4.直接到数据窗口,选择第一个DWORD数据,然后右键,【断点】,【硬件访问】。
5.然后直接按下【F9】让程序直接跑起来,这时OD会停在以下代码区域。
6.接着按下【F8】这里按下3次,最后看到下面的代码处,好了已经到OEP的位置了。
7.然后直接脱壳,直接点击右键,然后选择【用OllyDump脱壳调试进程】。
8.直接点击【获取EIP作为OEP】,然后点击【脱壳】,直接保存文件即可完成。
单步跟踪脱壳法
单步跟踪法是软件脱壳中最基础的脱壳技巧,单步跟踪法就是利用OD的单条指令执行功能,从壳的入口一直执行到OEP,最终通过这个OEP将原程序dump出来
在使用单步法的脱壳时,要注意关键的CALL,如果CALL指令步过后程序被运行起来则说明跑飞了,需要重新加载程序,下次运行程序后在跑飞的位置使用F7进入CALL中继续执行,循环往复直到找到正确OEP位置,有时候需要重复执行很多次,沉住气慢慢来。
1.首先我们使用OD载入附件中的【PECompact.exe】程序,然后会看到以下代码。
2.我们直接单步【F8】向下执行,看到哪里程序会跑飞,如下执行到【call ZwContinue】这个CALL时,程序跑飞,我们直接重新载入程序然后【单步F8】,到这个位置之后按下【F7】进入CALL的内部。
3.进入CALL的内部后,我们还是【单步F8】,这次很短暂,第一个CALL的位置就跑飞了,如下。直接重新载入程序,到这里后【F7】进入。
4.进入上图中的CALL的内部以后,我们不用管代码长啥样,直接【单步F8】,执行到下图所示的位置,发现一个JMP指令,继续单步跟踪。
5.然后会发现第二个JMP指令,嗯!直接【单步F8】执行这个跳转,离OEP已经很近了!
6.JMP指令执行跳转以后,会发现已经到达了程序的OEP位置,我们按照上一个案例的方法直接保存文件即可脱壳成功。
二次断点脱壳法
二次断点法也叫做内存镜像法,其流程是首先在程序的.rsrc资源断设置一个断点,然后在程序的.text代码段设置一个断点,或是在00401000处也就是解码段设置断点也可,然后运行程序,能够很快速的定位到程序的OEP位置。
1.首先我们使用OD载入附件中的【UPX.exe】程序,并打开【选项】-> 【调试选项】 -> 【异常】 -> 【忽略所有异常】。
2.不要运行程序,直接按下【Alt+ M】 切换到以下模块,选择.rsrc资源,并下一个【F2】断点。
3.接着按下【Shift+F9】,然后再次按下【ALT+M】,再次来到了这个位置,我们在【00401000】处下一个【F2】断点。
4.下好断点以后,我们直接按下【F9】让程序跑起来,然后程序会自动的断下,如下到达了程序的OEP了,直接保存文件即可。
堆栈返回脱壳法
通过观察程序的堆栈情况,我们同样可以完成脱壳工作,本次我们来脱一个FSG壳,这个壳需要自己查找并计算IAT,工具自动查找出来的地址是有误的,所以稍微有点难度,不过没关系,我们还是可以完美的脱掉它。
1.首先我们使用OD载入附件中的【FSG.exe】程序,这里我们直接运行起来,然后会看到如下图这样的代码。
2.接着我们观察一下堆栈情况,找到【SE 处理程序】,然后选中它,按下【Enter】跟随过去。
3.跟随过去以后,会发现一堆的DB数据,这是OD帮我们分析了代码,我们只需要【右击】选择【分析】然后【从模块中删除分析】,原始的代码就会出现。
4.删除分析以后,再看堆栈会发现,多出来了一个黑条,我们顺着黑条到断首,然后逐一排查。
5.这里有个查找技巧,我们的程序解码段是【00401000】,我们就找离这个地址最近的地址,此处是【0045C945】。
6.在【0045C945】的地址处,按下回车,就可以在反汇编窗口处看到以下代码片段,我们顺着代码向上找,看有没有OEP。
7.嗯!我找到OEP了,那接下来我们就想办法让程序运行后停在这个位置,我们直接在OEP的位置,【右键】,选择【数据窗口中跟随】
8.然后在数据窗口选择,【断点】,【硬件执行】断点,然后重新载入程序,并运行程序。
9.发现程序在运行时会自动断下,直接按下【Ctrl +A】分析代码,如下可以看到我们已经到达了程序的OEP。
10.我们记下【0005C865】,然后在打开【Lord PE】,选择待脱壳进程,然后点击【完整脱壳】。
11.接着打开【Import REC】,填入OEP的地址【0005C865】,点击自动搜索,这里需要注意,找到的RVA和尺寸是错误的,我们需要手动查找,我们记下【0007C170】。
12.这里输入【0047C170】,为啥是0047C170 ?我们的基地址是【00400000】和【0007C170】相加得到的【0047C170】。
13.定位地址以后,然后选择【长型】,选择地址。
14.向上找,观察发现程序的起始输入表地址是【0047C000】,结束地址是【0047C69C】,中间的【7FFFFFFF】则是需要删除的指针。
真实RVA:0007C000
真实尺寸:7C69C – 7C000 = 69C
15.填写上我们计算好的地址,然后点击【获取输入表】,接着显示无效函数,手动删除无效指针,并保存文件,即可脱壳成功。
写教程不容易,转载请加出处,您添加出处,是我创作的动力!