手动脱壳简简单单.docx
手动脱壳简简单单手动脱壳简简单单 在我们进行逆向分析的时候,通常会遇到有些文件被加密处理过,也就是我们通常所说的被加了壳,这时他的内部结构都已经改变,我们想要继续分析是很麻烦的,所以我们需要把它从壳中分离出来,也就是我们常说的脱壳。现在越来越多的软件都使用了加壳的保护方法,所以脱壳是我们在逆向分析过程中很主要的步骤,掌握它至关重要 壳是最早出现的一种专业加密软件。不同的壳的侧重点也不同,有的侧重于压缩,有的侧重于加密,所以出现了压缩壳和加密壳。压缩壳的特点是减小软件的体积,我们常见的有:UPX,ASPack,PECompack等。加密壳的则侧重于加密,保护强度较大,常见的有:ASProtect,Armadillo,Themida等。 第一步 寻找OEP OEP:程序的原入口点,就是壳程序在完成了对原程序的还原后,开始跳转到刚还原的程序执行,此时的地址就是入口点的值。 1 单步跟踪 首先,我们运行peid, 将我们要检测的程序拖到上面,可以看到它是用aspack加的壳,如图1。我们运行OD,点击菜单栏中的“文件”“打开”,把我们需要脱壳的文件加载进来,接着就会弹出一个对话框“模块你仍要继续分析吗”, 如图2,我们选择“否”,程序就会停以下的代码处: 01013001 > 90 nop 01013002 60 pushad 01013003 E8 03000000 call 0101300B 01013008 - E9 EB045D45 jmp 465E34F8 0101300D 55 push ebp 0101300E C3 retn 0101300F E8 01000000 call 01013015 01013014 EB 5D jmp short 01013073 我们按F8来跟踪一下,当到了call 0101300B这里的时候,记事本自己打开了,我们按Ctrl+F2重新载入文件,再来跟踪,当我们再次遇到call 0101300B这一句的时候我们按F7跟进,代码会来到这里: 0101300B 5D pop ebp 0101300C 45 inc ebp 0101300D 55 push ebp 0101300E C3 retn 我们继续F8来跟踪,当到了retn一句时,程序返回了,停在了 call的下面一句jmp 465E34F8上,跳转以后代码来到了下面的这一句call 01013015,继续F8,如果遇到程序往回跳,那么我们就在下一句代码处按F4,这样跟踪一段时间以后,我们会看到这样的代码: 010133BB 68 9D730001 push 0100739D 010133C0 C3 retn 再F8一下我们的程序就返回了了这里: 0100739D 6A 70 push 70 0100739F 68 98180001 push 01001898 010073A4 E8 BF010000 call 01007568 到这里,我们就已经到达OEP,单步跟踪法测试成功。 2 堆栈平衡 堆栈:一种数据项按序排列的数据结构,只能在一端(栈顶)对数据项进行插入和删除。 ESP:是CPU中的寄存器,它的值是指向堆栈栈顶的指针。 加壳时,必须保证加壳后文件与我们的原始文件的环境现场是不变的,所以在外壳程序运行的时候,就会把刚载入时的各寄存器值保存到堆栈中来保护环境现场,所以我们在它向堆栈保存环境现场时对这时的堆栈栈顶设置硬件访问断点,当壳程序执行完毕,恢复环境现场时就需要访问在保存环境现场时的堆栈地址,而我们已经在这里设置了硬件访问断点,所以程序就会被断下来。 在根据堆栈平衡原理,首先要说的就是ESP定律法。 在OD中载入我们需要脱壳的文件,注意OD右上角寄存器窗口中的ESP值,刚载入的时候它是红色的,我们按F8跟踪一下,当它再次变红时,如图3, 这时我们在OD左下脚的指令窗口中输入hr(hw) 当前ESP值,按回车,来设置一个硬件访问断点,如图4, 接着我们按F9让程序运行起来,代码会来到如图5所示的地方, 按只需要在这里按F8跟踪一下,程序就会跳到OEP了,ESP定律法测试成功。 有一部分加壳软件在保存和恢复现场环境时会使用pushad和popad指令。那么当我们在程序中遇到popad指令时就说明外壳程序已经开始恢复现场环境,准备返回OEP了,所以我们也可以通过搜索popad指令的方法来寻找OEP了。 打开OD把我们要脱壳的文件加载进来,按快捷键Ctrl+f搜索popad指令,如图6,点“搜索”,在如图7的地方我们找到了一处popad指令, 我们选中这一条指令,在上面按F4运行到这里,看这里的代码: 010133B0 61 popad 010133B1 75 08 jnz short 010133BB 010133B3 B8 01000000 mov eax, 1 010133B8 C2 0C00 retn 0C 010133BB 68 9D730001 push 0100739D 010133C0 C3 retn 我们来F8单步跟踪一下,当运行来到最后一句的时候,代码就会跳到这里: 0100739D 6A 70 push 70 0100739F 68 98180001 push 01001898 010073A4 E8 BF010000 call 01007568 这里就是程序的OEP,搜索popad指令法测试成功。 3 内存断点 程序在加壳时,会对原文件进行加密压缩,在执行加壳后的文件时,则会读取被压缩的代码进行解密,这时我们在被加密的部分设置内存断点,那么加壳程序在读取被加密的代码时就会断下来。 将加壳后的文件载入OD,按快捷键Alt+m打开内存窗口,找到第一个代码段.text选中它在上面按F2下一个断点,如图8, 按F9运行,它在第一个call的地方停下了,我们再按一次F9就可以看到我们设置的内存断点自动取消了,这时我们再F8跟踪几下,就到达程序的OEP了,内存断点法测试成功。 4 动态链接库 动态链接库在运行结束的时候还会来到程序的入口点一次,根据这个特征,我们还有一种专门针对动态链接库的OEP寻找法,我就以OD目录下的DBGHELP.DLL给大家做演示。 把我们需要脱壳的文件载入PEID,如图9,已经用ASPack加壳了,我们把它载入OD,会提示“文件*是一个动态链接库,windows无法直接启动,要启动loaddll.exe吗?”如图10,我们选择“是”,按n次F9让它运行起来,如图11, 现在我们把上面的那个小窗口给关闭了,OD会来到外壳程序的入口点,按F8跟踪,当遇到第一个call时按F7跟进,因为这是第二次运行外壳程序,所以程序会略过解密部分,接着F8再来跟踪,很快就会来到程序的OEP了,如图12, 我们已经来到了程序的OEP处,在OD工具栏的插件中选择“OllyDump” “Dump Debugged process”,如图13, 这时会弹出一个如图14所示的窗口, 我们只要按一下Dump按钮,把文件保存起来就可以了,用PEID查看一下Dump后的文件,如图15, 已经脱壳成功了。 LoadPE抓取DLL 首先我们让OD来到DLL的 OEP处,然后我们打开LoadPE,在上面的窗口中选择loaddll的进程,下面的窗口选中我们载入loaddll的DLL进程,点击右键选择“dump full”保存起来就好了,如图16 重建输入表 在加壳过程中,破坏原程序的输入表是必有的功能,在Dump后重建输入表也是非常关键的。 ImportREC是很专业的输入表重建工具,首先我们要确保我们已经找到程序的OEP,并且文件已经Dump,而且正在运行中。 打开ImportREC,如图17, 在上面的下拉框中选中,Dump后的文件进程,点击左下脚的“自动查找IAT”,在点击先面的“获取输入表”,最后点击“修复转存文件”,包修复好的文件保存起来就OK了。 到此为止,我已经介绍了所有的基本脱壳方法