ESP定律脱UPX的壳和IAT修复
上次发的IAT修复的图片不清晰,排版混乱,造成不便,十分抱歉。这次听取评论区大佬的意见,选择这篇文章在虚拟机内发布,希望可以有效改变之前的问题。这次还是讲讲脱壳吧!
首先要脱壳的话我们肯定得知道什么是壳,我们为什么要脱它,又要怎么脱。
先解释一下什么是壳:壳是一种保护文件的手段,一般分为加密壳和压缩壳两类,它会对PE文件里的资源进行压缩或者加密,被加壳的程序无法直接看到源代码,但不会影响正常的程序执行。简单来说就是在程序运行前给程序套上了一个王八壳子,有这王八壳子挡着我们无法直接看到程序的源代码。
解释完什么是壳,那么为什么要脱壳就很好理解了,这王八壳子不给它脱了,它对PE文件里的资源进行压缩或者加密是会让我们十分的难受,但最主要的是怎么脱,脱壳的方法有很多,比如ESP定律、单步大法、一步到OEP等等,那在脱壳之前我们先了解一下一般的壳是咋运作的:
首先先解释一个问题,加壳对PE文件里的资源进行压缩或者加密后源程序是怎么正常的运行的,这是因为压缩或者加密后的文件的解压缩或者解密过程是完全隐蔽的,都是在内存中完成的,可能你感觉这是在说废话,加壳的程序不在内存中完成解密或解压缩,难道还要用户自己去解密或解压缩。我们继续讲,壳是附加在源程序上的,它们通过Windows加载器加载到内存后,壳会先于源程序运行,从而获得控制权,继而在执行过程中进行解密或解压缩操作来还原程序,还原成功后再把控制权还给源程序,这样就可以正常执行原来的代码部分。
现在知道了壳是怎么运作的,那我们接下来脱壳就更加的容易操作和理解了。
我先用ESP定律脱壳做一个示例:
我们要脱壳,那么就需要知道这个程序是什么壳,所以在脱壳之前先进行查壳工作。
这里的示例在爱盘中有下载,是吾爱破解培训第二课作业。我们可以看到这是一个UPX的壳,用ESP定律正合适,ESP定律原理这里讲的话太长了,大家可以去搜一下。
可以从上图看到单步步过后,寄存器窗口只有EIP和ESP显示为红色,就是只有这两个寄存器的值被改变了,可以从汇编代码窗口看到第一句执行的代码为pushad,就是将所有32位寄存器压入堆栈,方便以后调用,因为堆栈平衡的缘故,在到达OEP之前肯定会使用popad将所有32位寄存器释放出栈,那么ESP现在所记录的位置是存放32位寄存器的位置,当使用popad的出栈的时候肯定需要访问这个位置,所以我们只需要对这个位置的数据下一个硬件访问断点,就可以找到对应的popad的位置,从而找到OEP。
这里数据划拉的长度和硬件访问断点的长度随你选择,我们对这个位置下好硬件访问断点后,点击运行,就可以看到上面那条代码就是popad,下完硬件断点后要记得去‘调试’选项卡里将刚下的硬件断点给删掉,不然以后可能会有点碍事。
我们还可以看到下面有一个jmp从005BABDD跳转到005025A6,这可是一个大跳转,005025A6极有可能是OEP,我们直接跳转到005025A6看看。
跳转到005025A6后可以看到第一句代码就是一个call,第二句代码是一个jmp,这让我确信了这是一个OEP,下一步我们就需要进行dump,这里我用的是OD的dump。
右键反汇编窗口,点击‘用OllyDump脱壳调试进程’,出现如下图所示。
我们可以从上图中看到一个选项‘重现输入表’,建议重建输入表和不重建输入表各搞一个,选择好后点击脱壳,另存为一个新文件即可。
如果这里你出现了问题,那么有可能是因为ASLR进行了基址随机化,你需要按ALT+E去看看载入的第一个模块的基址是多少,将载入的第一个模块的基址替换掉上图中起始地址的400000,应该就可以点击脱壳,从而继续下面的步骤了。
我这里将两个dump的程序命名为11.0和11.1,下一步我们尝试打开应用程序,看看哪个能够使用。
我们可以看到11.0无法使用,显示‘无法定位程序输入点XXX于动态链接库11.0.exe上’
我们可以看到11.1也无法使用,也显示‘无法定位程序输入点XXX于动态链接库11.1.exe上’
简单来说这里出现了这种问题是因为一些API无法正常加载到程序中,我们程序的IAT出了问题,所以下一步就是需要修复IAT。
修复IAT这里所需要使用到的工具是ImportREC,这个工具可以在爱盘中下载。
加载进ImportREC当中后,点击上方的下拉框,选择需要脱壳的程序,这里有一点需要注意,需要将要脱壳的程序加载进OD,这里才会显示需要脱壳的程序,不然是找不到的。
从上图我们可以看到OEP显示为001BAA00,明显获取到的OEP不正确,我们去OllyDump中复制OEP修正地址,然后把它粘贴上去。
改正OEP后,我们还需要去找到RVA,这里就不细讲IAT和RVA,简单来说IAT就是一个用来记录加载到程序进程空间中API的地址的表,这里的RVA是IAT表相对于基址的偏移地址。这里我们可以使用两种方法,这两种方法都是基于一个原理,那就是加载到进程空间中的API的特征码为FF 15。
第一种寻找RVA的方法:
先随便进入一个call,然后我们寻找特征码为FF 15的call,就像下图:
可以看到上图的四个call的左边都有一串字符为‘FF 15 XXXX’的特征码,我们随便选一个特征码为FF 15的call,然后右击‘数据窗口中跟随’=》‘内存地址’,这样就能跟随到存放call跳转地址数据的地址。
可以看到数据窗口也看不出啥玩意,因为我们需要修改一下数据窗口的显示类型,右击选择‘长型’=》‘地址’,就可以出现如下图所示。
这里我们可以清楚的看到地址,地址中存放的数值,以及对存放的数值的解释,我们需要往上翻,直到翻到连着好些数值为0的时候。
从上图可以看到第一个开始记录API载入地址的是00527000,那么我们的RVA就是00527000 - 基址,我这里的基址为400000,所以得出RVA为00127000。
大小则是往下翻,翻到数值是以00开头的时候,如下图
大小是最后一个存放API的地址减去第一个存放API的地址,我这里就是0052795C - 00527000 = 95C,大小可以比真实的大小大,但不能比真实的大小小。
这样我们就获取到了RVA和大小这两项信息,还有一种方法其实就是按CTRL+B在特征码栏搜索FF 15,后面都是一样的。
自此这两种方法都讲完了,我们继续修复IAT。
填好信息后,点击获取导入表,我们所要做的就是删除无效的导入表函数,我们继续点击‘显示无效的’,右击无效的导入表函数,点击‘删除指针’
成功处理了无效的导入表函数后,我们点击右下角的‘修正转储’,将IAT修正好的程序转储到之前IAT修复失败的程序,也就是之前脱壳后打不开的程序,我们的IAT修复就圆满成功了!
修正转储后的程序会在原本的程序名后面加一个_以表示区别,我们来运行程序看看是否有问题。
11.0_.exe运行成功!!!至此我们完成了脱壳和IAT修复。 tl;dr 发表于 2023-1-5 13:45
esp定律是啥?
ESP定律是一种利用堆栈平衡进行脱壳的方法,这玩意你可以理解为有一个窄而高的盒子,在程序运行开始后,会往盒子里放东西,放在最底下的因为上面压了东西,所以要把上面的东西取出来才能拿它,当你进入程序后,第一句是pushad,就把所有的32位寄存器给放入了这个盒子,后面的程序它会往里面放东西,也会往里面塞东西,但不管怎么样,最后都会使用popad将32位寄存器给拿出来,想要拿出来那不就得把上面的所有东西全部给拿出这个盒子,所以下了在这个放32位寄存器的·地方下了一个硬件断点,什么时候来拿这个东西就什么时候给断下来,然后再走几步就可以到OEP了。 silly123 发表于 2024-3-14 09:19
感谢楼主,这就是我想要得,但我有个小问题,加壳后的程序用IDA打开是只显示加密过程函数吗?还是每个程序 ...
对于加壳程序,在使用IDA打开时可能会出现不同情况。一般情况下,加壳程序在IDA中可能会显示加密过程函数,因为加壳程序会对原始程序进行加密或混淆处理,使得IDA无法直接识别和展示原始程序的代码。
但是,具体情况取决于加壳程序的加壳方式和加密算法。有些加壳程序可能会在IDA中展示加密过程函数,而有些加壳程序可能会在IDA中展示解密过程函数,甚至有些加壳程序可能会在IDA中展示部分原始程序的代码。因此,每个加壳程序的情况可能会有所不同。 学习一下哈 学习学习,精彩的教程{:1_921:} 学习学习,精彩的教程 这真的好难。牛b 精彩课程,好好学习 学习了...... 大神,分析的太详细了。GOOD 谢谢分享!!