前言
这是CreakMe的第五个程序,CKme002。由于在研究过程中,发现该程序存在加壳,因此本篇主要用来记录脱壳过程。
壳原理
为了保护源程序,通常会给源程序披上一层“外衣”。这层“外衣”就是壳,壳也是一段代码,用来加密或压缩源程序,使得源程序不易被人利用。当运行程序的时候,首先会运行壳程序,壳程序会解压缩或解密源程序,执行完毕后,将控制权交给解压缩或解密的程序。
脱壳方法
自动脱壳机手动脱壳手动脱壳的原理,简言之,就是找到程序的OEP,然后将程序dump下来,然后确保程序可以正常运行。
操作过程
自动脱壳和手动脱壳可以相互应证,确定无误。
使用Peid查看CKme002,发现存在壳upx,
然后这里首先使用插件Peid通用脱壳器对程序进行检测,发现入口点为0044768C。
此时点击脱壳,理论上就可以完成脱壳。但是本地点击脱壳后,就非常卡顿,故就先记录这个入口点。
(一)一步到达 OEP ----搜索popad
打开OllyDbg,载入程序,发现这里有很多线索,比如pushad,ESP爆红。
pushad,是指将eax、ebx等寄存器全部压入到栈中;与之对应的是popad,将eax、ebx等寄存器全部出栈。
因此这里就选用最简单的方法,搜索popad,
果然找到了一处popad,并且下方存在一个jmp大跳转
00477B8E > \61 popad
00477B8F .- E9 F8FAFCFF jmp CKme002.0044768C
在此处下断点,然后运行程序,发现果然源程序没有弹出窗口。然后单步跟踪,发现一个十分可疑的地方,即“push ebp;mov ebp esp”,开辟栈空间。
继续往下调试运行,即弹出源程序界面。
因此断定此处就是OEP入口。对比工具的检测,地址是一样的,都是0044768C。
然后dump程序,修改OEP,脱壳即可。
但是在运行dump程序时,发现异常。
这是由于IAT出现了问题,使用汉化版importrec,载入程序,
修改oep和新建输入表信息,然后修复刚刚dump的文件,并保存。
再次查壳,发现已经无壳了。
并且程序可以正常运行。
(二)下面分享几种其他的脱壳方法
ESP定律
F8,单步跟踪,发现ESP为红色,值发生变化,说明此时壳程序准备入栈。
然后右键ESP的值,选择HW break[ESP],(可在硬件断点处查看)
然后F9运行程序,程序出发断点,停到了popad附近。
本次还尝试了内存镜像法、最后一次异常法和SFX法,但是发现这里不使用。内存镜像法需要对资源段和代码段下断点,但是本次下断点效果并不理想;最后一个异常法和SFX法均效果不佳。
下面总结几个通过本篇,学习到的知识:
单步跟踪法的原理就是通过 Ollydbg 的步过 (F8), 步入(F7) 和运行到 (F4) 功能, 完整走过程序的自脱壳过程, 跳过一些循环恢复代码的片段, 并用单步进入确保程序不会略过 OEP. 这样可以在软件自动脱壳模块运行完毕后, 到达 OEP, 并 dump 程序。
ESP 定律的原理在于利用程序中堆栈平衡来快速找到 OEP。
一步到达 OEP 的脱壳方法, 是根据所脱壳的特征, 寻找其距离 OEP 最近的一处汇编指令, 然后下 int3 断点, 在程序走到 OEP 的时候 dump 程序。
内存镜像法的原理在于对于程序资源段和代码段下断点, 一般程序自解压或者自解密时, 会首先访问资源段获取所需资源, 然后在自动脱壳完成后, 转回程序代码段. 这时候下内存一次性断点, 程序就会停在 OEP 处。
最后一次异常法的原理是, 程序在自解压或自解密过程中, 可能会触发无数次的异常. 如果能定位到最后一次程序异常的位置, 可能就会很接近自动脱壳完成位置. 现在最后一次异常法脱壳可以利用 Ollydbg 的异常计数器插件, 先记录异常数目, 然后重新载入, 自动停在最后一次异常处。
"SFX" 法利用了 Ollydbg 自带的 OEP 寻找功能, 可以选择直接让程序停在 OD 找到的 OEP 处, 此时壳的解压过程已经完毕, 可以直接 dump 程序。
几个本人觉得不是很常见的指令:
adc:指令将源操作数和进位标志位的值都与目的操作数相加sar:算术逻辑右移sal:算术逻辑左移xchg:寄存器和内存变量之间内容的交换指令
分享好文:
加壳与脱壳理论详解 - 菜鸟-传奇 - 博客园 (cnblogs.com)
ESP 定律法 - CTF Wiki (ctf-wiki.org)