DLL文件脱壳

时间:2024-04-10 16:38:24

博客中用到的例子和某些程序的链接在文章末尾。

对DLL文件进行脱壳的原理和对普通PE文件进行脱壳的原理其实是差不多的,就是多了一个构造重定位表的步骤。因为DLL文件都是映射到其他进程的地址空间中,所以基址很有可能不是默认基址。而壳又会破坏原来的重定位表,所以我们脱壳后需要手动构造一个新的重定位表。

第一步,也是需要像脱普通PE文件的壳一样,先找到OEP,然后再把镜像文件给Dump下来。但是因为重定位的关系,我们又希望脱壳后的文件尽量和脱壳前的一样,所以我们就需要找到壳中进行重定位的那一段代码,然后将其跳过,再把这个时候的内存数据给Dump下来。

首先我们肯定是要把DLL文件给拖入OD的,OD中有一个专门用来调试DLL文件的程序:loaddll.exe。当你把DLL文件拖入OD的时候,OD会自动询问你是否要用这个程序来调试DLL文件,点击确定。完成后会有一个蓝框的小窗口。

DLL文件脱壳

长这个样子。但是在这个时候,DLL文件已经被加载进去了,也就是说已经被脱壳并且重定位的操作也已经完成了 。这就很头疼了。我们必须得让程序停在壳的入口处,那么我们就在它加载完后看看,按下  Alt+M或者鼠标点击OD那个小框框的M按钮。

DLL文件脱壳

找到这个DLL文件,可以看到最下面那个节就是多出来的节,也就是壳所在位置,从这里可以得出壳入口偏移为D000。然后我们在反汇编窗口中查看一下:
DLL文件脱壳

记住开始的这两个指令的机器码:60 e8。因为我们待会要改动这个入口点的代码,让程序刚加载就停在这里。我们使用LordPE的PE编辑器来完成这个操作。我们打开LordPE然后点击PE编辑器,然后选中目标DLL文件,然后点击位置计算器,再在RVA的框中输入壳的入口偏移:D000。点击执行,再点击编辑,然后将入口的 60 e8改为EB FE(如下图), 这个指令是一个循环跳转,就等于是jmp 到自己的位置,所以在程序第一次加载DLL的时候程序会一直在第一条代码处循环,到时候OD可能会什么都显示不出来,这个时候点击调试,然后再点击暂停就可以了,最后我们再把代码改回来然后再调试就可以了。

DLL文件脱壳

做完上面这些后,我们就要开始寻找壳中进行重定位的操作并且跳过它,这样我们脱壳后的文件中关于内存地址的操作的基址都是默认的40000。

步入壳入口的第一个函数,然后逐步单步跟踪。如果有看到类似于下图这种做减法的操作,那么重定位差不多就是在这里。顺着这个地方看,可以看到有个OR指令,再看看它上面的代码,基本可以推断出,这个OR语句是在比较目前的基地址与默认基地址,如果相同就不用进行重定位,不同就要进行重定位。

所以,JE跳过的那段代码,就是重定位的代码。

DLL文件脱壳

我们直接把JE修改为JMP进行强制跳转(下图)。再单步跟踪到OEP的位置,找OEP的方法就不再介绍了,之前一篇博客里面有写。

DLL文件脱壳

上面这种方法找重定位代码只适用于这种简单的壳,如果碰到不简单的,还是得用下面这种方法:

首先,也是得先让程序停在入口点,再把代码改回来再调试。然后我们在内存映像基址窗口找到代码段的地址

DLL文件脱壳

进入,然后随便找一个对内存进行操作的指令。比如下面这个

DLL文件脱壳

这个指令的地址是:005a10a0。当壳要进行重定位的操作时,就要对这些指令中的关于内存地址的数据进行改动,那么就会对这个指令所在的地址进行访问,所以我们在这个地址上下一个写入断点。在命令窗口写入:hw 005a10a0。然后运行程序,程序会断在重定位代码的附近,然后再去找就容易多了。

DLL文件脱壳

调试停在OEP位置后就用LordPE把内存数据给Dump下来。(如下图)

DLL文件脱壳

Dump 下来后还要重建文件的输入表,还是使用Import REC软件,在下拉栏里面选择loaddll.exe进程,然后在右边再选择加载的DLL文件。注意:要在选项中取消使用来自磁盘文件的PE头的选项(如下图),因为如果用磁盘文件的PE头,那么就会使用默认的基地址来计算RVA,而我们加载进去的DLL的基址很可能不是默认基地址。到时候就会出错。

 DLL文件脱壳

在IAT自动搜索的左侧输入DLL入口偏移,这里是1240,然后点击IAT自动搜索,很有可能搜索不到,这个时候就要手动填入IAT的RVA以及大小。在内存映像窗口可以看到输入表所在的节的起始位置是2147000,偏移是7000。

DLL文件脱壳

到内存窗口中查看,因为IAT表最后是以一个双字的0结束,并且可以从下图中看出,很容易看出内中数据的不同,所以IAT的结束位置就是标记的那个地方,所以IAT的RVA是7000,大小是E8。我们手动填入,然后点击获取导入表,然后再点击修正转储,选择之前dump 下来的文件。完成。

DLL文件脱壳 

 完成上面那些步骤后,该DLL文件的输入表算是重建完了,但是最重要的重定位表还没搞完。将原先的DLL文件重新载入OD,这里也是需要改变壳入口点代码然后使其停在入口点,然后再一步步跟踪调试。

利用上面的方法找到重定位的地方,分析代码如下图:

 DLL文件脱壳

 这里首先要说明一下目的,我们需要导出所有的重定位数据,然后用一个软件来构造重定位表。所以我们在这里要写一个补丁来获取所有的重定位信息。

首先我们要申请一块内存来存储得到的重定位信息。使用下图所示插件,如果没有插件可以在网上下载。

DLL文件脱壳 

 按上图操作后内存窗口会显示一块内存,然后我们向里面填入地址(如下图):

DLL文件脱壳

然后分析上面的重定位代码可以得出,在or al,al那条指令那里,寄存器EBX中存储的就是需要进行重定位的代码的地址。我们就在那里进行跳转,跳转到我们的补丁代码处,该补丁获取重定位数据,然后存放到我们申请的内存处。补丁代码如下图:

DLL文件脱壳

 运行之后,得到所有的重定位信息。

DLL文件脱壳 

然后进行如下图所示的复制操作。(要注意复制不包含开头那两个字的0,但是包含最后结尾的两个字的0)

 DLL文件脱壳

打开WINHEX,粘贴。(要注意结尾是不是比原来多了0,结尾是只有两个字的0的)

DLL文件脱壳 

最后导出文件,后缀名为  .bin  文件名随便。

DLL文件脱壳 

 然后我们打开ReloREC软件,将导出的文件拖入,再输入重定位表的RVA,该RVA也在虚拟内存映射窗口中找到(如下图)

DLL文件脱壳 

最后点击fix dump选择我们之前修复了输入表之后的文件。

DLL文件脱壳 

完成后就大功告成了,运行程序,成功!

DLL文件脱壳 

 

博客中所需软件大部分可以在吾爱**网站下载,然后其他实现所需程序:

链接:https://pan.baidu.com/s/1rb2lAm15Nhu9qImLyYJPOQ
提取码:zkfh