OD载入
004656C0 U> 60 pushad // 壳的入口
004656C1 BE 00004400 mov esi,UPX_0_89.00440000
004656C6 8DBE 0010FCFF lea edi,dword ptr ds:[esi+FFFC1000]
004656CC C787 9CC00400 4>mov dword ptr ds:[edi+4C09C],2BAC034C
004656D6 57 push edi
对于UPX壳OD载入后,F8单步走到004656C1行,然后在命令行输入hr esp,回车后F9运行,下图所示
按F7单步进入,就到达OEP!
可以Dump,为了下一步的文件优化,这里我们要把Dump下来的dumped.exe做一个备份(备份为dumped.rar),然后可以用ImportREC修复、保存,OK!脱壳成功。这样修复保存得到是传统的方法(即在区段表的最下面添加上一个.mackt区段),下面讲解完美脱壳。
二、优化-完美脱壳
1.为什么脱壳后要优化?
答:很多壳会合并区段,并且添加壳段,如果脱壳后不优化,则会增加脱壳后文件的体积,降低程序的运行效率。
2.如何进行优化?
答:想要完美脱壳,就需要还原原始区段,并且去掉壳段,有必要时还要减小文件对齐,从而缩减文件中的“00”,使得脱壳后的程序在PE信息上尽量靠近原始无壳程序,文件体积与无壳文件相似或更小。
一般优化步骤:
1、寻找并记录各项信息(OEP、基址、对齐、区段分离、输入表、输出表、资源表、重定位表、TLS表);
2、重建PE头;
3、修复PE头各项信息,修改段属性(注意:这里最好清空输入表和资源表目录信息,防止被部分系统中的dumped.exe神不知鬼不觉的插入到进程explorer.exe中);
4、修复IAT(有可能不需要!);
5、重建资源;
6、更改段属性,清理附加数据。
下面开始进行优化:
1、这里主要是记录区段信息,分离被合并后的区段。
①.怎么样找Delphi程序的数据段?一般来说delphi程序的数据段有这么一个字符串“runtime”我们通过查找字符串确定DATA数据段。将无壳程序载入OD,在数据窗口,右键->查找->二进制字符,如图所示。
可以快速找到Delphi程序的数据段,向上到数据段起始位置44D000。根据段连续,那么CODE代码段自然是从PE头结束位置1000-4C000 处
CODE 代码段 1000-4C000
DATA 数据段 4D000-2000 //数据段大小一般是2000;
BSS BSS 段 4F000-1000 //根据段连续,BSS段就是4F000
.IDAtd 段 50000-3000 //这里有一个技巧,用ImportREC修复,Size大小需要24E8,所以我们不能按原始 的数据大小还原,应改为3000; .tls TLS表 53000-1000 //TLS原本是52000,根据段连续就是53000;
.rdata 段 54000-1000
.reloc 重定位 55000-1000 //在完美脱壳时会清空内容,填充“00”,所以象征性的填入1000;
.rsrc 资源段 56000- //资源段只需要给出RAV,不需要给出大小,后面要重建资源表。
②.复制.tls段代码,选中00453000行,如图
按Shift+X可以复制无空格的代码:00204500102045009CD0440010304500
用“|”分隔:00204500|10204500|CD04400|10304500
00452000 - 00453000 //将.idatdd大小设置为3000,根据段连续和区段对齐将其设为00453000;
00452010 - 00453010 //根据段连续设为00453010;
0044D09C - 0044D09C //保留为0044D09C;
00453010 - 00454010 //根据段连续设为00454010。
2、重建PE头,有些加壳程序会把PE头改得一塌糊涂,所以,需要重建PE头。
①.需要找一个同类语言编写的文件Delphi7-无壳.exe,复制过来。
②.用C32ASM分别打开Delphi7-无壳exe和dumped.exe,我们要通过无壳程序来重建原始的PE头。将无壳程序的代码00000000~000003C0选中复制,转到Dump后的程序对应的地方填充00;然后,再粘贴;
③.因为在内存中PE头的大小是1000个字节,我们还需要再填充一点,在无壳程序中选中000003D0~00000FF0复制,在脱壳后的程序对应的地方填充00。这样重建的PE头只有前面400字节部分有代码,见图所示
3、在这一步我们修复PE头各项信息,修改段属性和清空输入表和资源表目录。把一个无壳程序的PE头复制过来,改掉这个PE头的各项信息。把区段标志改成E0000060,即可读可写的,方便后面修复IAT的操作。最好还是要清掉输入表和资源表信息,因为重建的PE头后,没有经过这两个表, Dump程序会插入到进程中,绕很大一个弯,还不知道自己摔倒在这个地方……。这是经验!
我们现在来还原PE头信息:
①.用LordPE载入修复PE头后的程序,并转到目录表,清空导入表、资源表、重定位表和TLs表,如图所示
②.还原区段,用上面1中编制的各区段的RAV值,编辑7个区段,最后的.rsrc资源段我们就不管了,因为我们后面要重建资源。
③.回到起始PE首部信息,将区段数目改成7。这里主要要注意几个地方:
A、文件块对齐需要手动修复为1000;
B、部首及块表大小。在部首及块表大小后面的“?”按钮点一下,数据自动改为1000;
C、入口点改为4CA98。注意保存!
D、数据段基址可以修复为4D000,也可以不修复,这里主要是给OD看的。
E、将效验值后面的“?”按钮点一下,可以看到修改后的全部信息,如图所示:
这里为什么要改段属性,主要是为了方便后面的修复IAT操作,这是一个经验和操作习惯,不修复段属性,后面的操作会出现一些莫名其妙的问题。
4、我们采用的是完美脱壳,对于压缩壳不需要修复IAT,但对于加密壳这一步是必须的。
①.下面修复IAT,ImpREC 加载UPX 0.89.6 - 1.02实例的进程,如下图所示。在ImpREC右边的新建输入表信息栏,将RAV的值填为:5000,因为,.idatd=00050000,大小自动显示为:24E8。注意:在进行IAT修复时,一定不要勾选“添加一个新的区段”。在ImpREC的选项中,应勾选“重建原始FT”和“创建新的IAT”,其它选项可以按照默认值。“按序号构建输入表”这一项我感觉不应该勾选!我是菜鸟,也说不出什么原因……;
②.修复后的dumped_.exe可以用LordPE和OD打开,但用F9或直接双击不会运行。这是还原区段后,原始区段里面的信息我们并没有清空所至;
③.用PE Tools载入修复后的dumped.exe程序,如下图所示,将BSS~.reloc区段逐个进行,右键->填充区段->用00填充,再用ImpREC转存到文件。
我们用LordPE来看它的信息,点按导入表后面的“…”按钮,查看函数情况,如图:
说明检查函数没有问题,我们再用OD载入,能停在OEP附近,OK!尽管修复后的程序还不能运行,但可以载入OD了,这样修复IAT完成。
5、一般我们是不用壳的资源信息,我们需要重建资源。
①.把前面做Dump后保存的文件dumped.rar解压出来,并用一个DT_Fixros Demo工具,把dumped.exe拖到DT_FixRes中的PE文件框中,转到“转存”页签,选定资源文件保存的路径和文件名,我们这里用.rsrc,扩展名用.bin.。新的RVA填为:56000(这是前面给资源段预留的值),文件对齐填入200,资源修复成功!
②. 用LordPE给段添加资源,从磁盘载入.rsrc.bin文件,如图所示。
进入编辑区段,将名称改为.rsrc(即去掉后缀.bi,目的是让区段表还原为原始表),将虚拟大小和物理大小均改为5400,将标记还原为50000040,如图所示。
下面还需要在目录中指定资源表的RVA=56000;长度=5400,保存。我们可以看一看,点按资源表后面的“…”,并没有什么错误,说明资源表修复是正确的,如图所示。
资源表修复完成!dumped_.exe的图标也出来了,运行还没有什么反映!这是什么原因呢?
③.OD载入dumped.exe,F8单步向下走,发现有错误,如图
大家要学会在修复的过程中,用OD载入来检查各种问题。这里的错误是我们还没有修复TLS表信息;
④.利用前面记录区段信息填充TLS表,在目录的Tls表填入RVA=54000(Tls表的RVA自然是.rdata的54000);长度=18。并在Tls表如图填入以下信息。
保存后,可以运行。OD载入后也可以运行,说明我们在Tls表将内存地址加1000是必须的。到此我们的TLS表修改完成!
6、更改段属性,清理附加数据。即把在3步改掉的段属性改过来;
①.这一步就是还原区段信息,如图所示
②. 清理附加数据就是在5步重建资源之前会把资源删除,如图
下面用FFI工具移出附加数据,如图
移出附加数据后查壳:Borland Delphi 6.0 - 7.0
③.比较原程序delphi7例子和完美脱壳dumped_.exe的文件的属性,如图所示:
完美脱壳后的程序比原程序还要小20KB,再看区段表更是完美脱壳!
以上文件脱壳后的优化是我学习天草老师教程做的学习笔记,我以为通过该实例:
1、认识PE并重建PE头;
2、熟悉一些小工具的使用。
拙文提供给像我一样的菜鸟学习和参考,高手漂过!