新书推荐:17.3.2 手工脱壳
不同的壳程序通常都会有一个对应的脱壳工具。但是多数情况下,必须进行手动脱壳。手动脱壳有时候很快,且不费精力。有时候却是一件费事且艰巨的过程。
■手动脱壳方法
手动脱壳程序的方法有两种:
●找到加壳的算法,然后编写一个程序逆向运行它。通过逆向运行这个算法,这个程序可以解开加壳程序的每一步操作。虽然有一些自动化的工具可以完成这些工作,但是这种方法效率很低,因为编写的脱壳程序仅针对单个的加壳程序。所以,即使辅以自动化,这个过程依然需要大量的时间来完成。
●运行脱壳程序,让脱壳存根帮你工作,让它从内存中转储出进程,然后你再手动修正PE头部,保持程序的完整。这是一种非常有效的方法。
接下来我们使用第二种方法解析下面的两个加壳程序。
实验一百一十六:FSG壳动态分析
让我们借助OllyDbg调试器调试跟踪加壳程序HelloWorld_fsg.exe,找到程序的OEP原程序入口地址。
■调试跟踪加壳程序HelloWorld_fsg.exe
将加壳程序HelloWorld_fsg.exe拖入OllyDbg调试器。从入口地址0x00400154开始按F8单步执行(期间可以使用F4跟随断点跳过循环,加快调试进程),直到跟踪到0x004001D1地址处,如下图所示:
图17-3 单步跟踪加壳程序到关键跳转语句
在0x004001D1地址处,按F8单步执行,跳转到原程序入口地址0x00401000。如图17-4所示。点击鼠标右键“分析”->“分析代码”就可以正确显示反汇编代码了。
此时,打开内存映像窗口,可以看到,加壳程序除了PE头之外,包含两个节区。第一个节区为代码段,第二个节区为输入表。双击代码段节区,数据窗口显示原程序的代码段。
此时,再双击第二个节区,打开数据窗口,如图17-5所示。和之前我们静态分析PE文件中第二个节区数据没有任何变化。说明这里的数据是只读数据,应该是在加壳时需要用到的额外数据。
图17-4 跳转到原程序入口地址
图17-5 查看加壳程序第二个节区数据
总结
如果需要动态调试加壳程序,关键是找到跳转原程序入口地址的JMP指令,剩下的事情和调试未加壳程序是一样的。动态调试的过程和静态分析是相互印证的过程。
此外,FSG加壳程序的PE头都会带有FSG壳的标识字符串“FSG!”,可以作为判断依据。
■手工脱壳
实验一百一十七:HelloWorld_fsg.exe手工脱壳
让我们借助OllyDbg调试器、LordPE、ImpotREC工具实现加壳程序HelloWorld_fsg.exe手工脱壳。
●HelloWorld_fsg.exe
第一步:使用OllyDbg调试器单步跟踪,跳转到原程序的入口地址(OEP)。
图17-6 跳转程序入口地址
第二步:使用OllyDbg插件OllyDump进行程序的脱壳操作。点击鼠标右键“用OllyDump脱壳调试进程”,弹出如下对话框窗口。
图17-7 dump脱壳程序
注意检查“起始地址”、“入口点地址”是否正确,不要勾选“重建输入表”选项,等待稍后修复输入表。点击“脱壳”选项,保存为OllyDump_HelloWorld.exe。
还可以使用LordPE工具dump脱壳文件。打开LordPE,选择当前正在调试的进程HelloWorld_fsg.exe,如下图所示:
图17-8 使用LordPE dump脱壳文件
点击鼠标右键“完全脱壳”,保存脱壳文件为dumped_HelloWorld.exe。使用LordPE工具dump下来的脱壳文件和使用OllyDump插件几乎完全一样。
第三步:修复输入表。如果使用纯手工修复是可以的。但是如果导入函数很多,可以借助于ImportREC工具修复导入表和IAT表。
打开ImportREC工具,附加当前调试的加壳程序HelloWorld_fsg.exe,如图17-9所示。
输入程序的OEP入口RVA地址00001000,然后点击自动查找,发现提示“在此OEP没有找到任何有用的信息!”。如果没有找到IAT信息,则要手动填入IAT的RVA和大小。
图17-9 自动查找IAT
使用WinHex打开dump文件OllyDump_HelloWorld.exe,我们会发现在文件偏移00002000H地址处有导入表和IAT表信息,如下所示:
00002000 A2 BF 81 7C FF FF FF FF EA 07 D5 77 FF FF FF 7F ⒖亅?誻
00002010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 . @.j @.. @.?@.
00002020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00002060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00002070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00002080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
00002090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
此时,查看调试器中的内存窗口地址0x00402000,如下图所示:
图17-10 查看OllyDbg调试器IAT表
内存地址0x00402000处存储的就是内存中的IAT表。我们据此修复PE文件内的IAT表就可以了。
因此,我们将OEP下方的“RVA”栏填写为:00002000,“大小”栏填写00001000。然后点击获取输入表。
图17-11 获取输入表
查看左侧窗口显示的导入函数,其中有些是无效的,点击“显示无效的”按钮,筛选出无效的导入函数,如图所示:
图17-12 筛选无效导入函数
然后在输入表函数栏点击鼠标右键“剪切指针”,删除无效导入函数。如下图所示:
图17-13 删除无效函数
最后点击右侧按钮“修复转储文件”,选择需要转存的dump文件,保存修复后的文件unpack_HelloWorld.exe。
第四步:运行修复后的文件,成功!对比修复后的变化。
将修复之后保存的文件unpack_HelloWorld.exe拖入WinHex:
节区二:
00002000 4A 60 00 00 00 00 00 00 64 60 00 00 00 00 00 00 J`......d`......
00002010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 . @.j @.. @.?@.
00002020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00002050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00002060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00002070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00002080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
4A 60 00 00 00 00 00 00 64 60 00 00 00 00 00 00为修复后的IAT表,对应节区三种中的函数导入表。
节区三:
00006000 00 00 00 00 00 00 00 00 00 00 00 00 3C 60 00 00 ............<`..
00006010 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 . ..............
00006020 58 60 00 00 08 20 00 00 00 00 00 00 00 00 00 00 X`... ..........
00006030 00 00 00 00 00 00 00 00 00 00 00 00 6B 65 72 6E ............kern
00006040 65 6C 33 32 2E 64 6C 6C 00 00 B7 00 45 78 69 74 el32.dll..?Exit
00006050 50 72 6F 63 65 73 73 00 75 73 65 72 33 32 2E 64 Process.user32.d
00006060 6C 6C 00 00 DD 01 4D 65 73 73 61 67 65 42 6F 78 ll..?MessageBox
00006070 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A...............
将unpack_HelloWorld.exe拖入OllyDbg,查看内存窗口:
00402000 >E0 3B 60 77 00 00 00 00 B0 FD 7B 77 00 00 00 00 ?`w....褒{w....
00402010 08 20 40 00 6A 20 40 00 00 20 40 00 84 20 40 00 @.j @.. @.?@.
00402020 00 00 00 00 4C 20 00 00 00 00 00 00 00 00 00 00 ....L ..........
00402030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00402040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00402050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4D 65 ..............Me
00402060 73 73 61 67 65 42 6F 78 41 00 75 73 65 72 33 32 ssageBoxA.user32
00402070 2E 64 6C 6C 00 00 00 00 45 78 69 74 50 72 6F 63 .dll....ExitProc
00402080 65 73 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C ess.kernel32.dll
IAT表已修复完成,可以正常运行。