首先了解一下壳的种类:压缩壳,加密壳,虚拟机壳
加壳的原理:加壳的原理通常是加密,压缩源程序的各个区段,并给源程序添加一个或者多个区段作为源程序的引导代码,然后将源程序的入口点修改为外壳程序的入口点。
(注意:通常而言,一些简单的壳,壳代码在原程序之前运行,当然,现在很多强壳已经达到了肉中有壳,壳中有肉的局面)
壳的解密例程负责解密,然后跳转至OEP处开始执行。
研究壳有一段时间了,打算发一些脱壳系列的文章,总结一下脱壳技巧,本篇为脱壳第一篇,后续将会发一些进阶系列的文章。
一般而言,脱壳的基本步骤如下:
1:寻找OEP(注意:OEP指的是程序原始入口点,不是壳的入口点,英文全称是(original entry point)
2:转储,也就是dump
3: 修复IAT(导入地址表,英文全称:import address table )
4:检查目标程序是否存在AntiDump等阻止程序被转储的保护措施,并修复
注:遇到一些外文名词,可以尝试找到其英文全称,这样更加有助于理解
常用的脱壳方法(此处介绍一些常见脱壳方法,若要提高自己的能力,务必动手多练)
1 一步直达法,搜索JMP(0E9)或者CALL(0E8)指令的机器码
对于一些简单的壳有效,例如UPX,ASPACK,原理:一般情况下,壳在解密完区段后会通过一个长跳转或者CALL跳转到OEP处。
下面举一个简单的例子:
一步直达法脱UPX壳:
首先,OD加载,断在了程序的入口点

ctrl+b

多按几次ctrl+l
直到出现如下界面,跳往第一区段

除了搜索jmp call 的机器码之外,还可以搜索call eax,jmp eax等指令的机器码,很多时候壳会将OEP的值存放在寄存器中,然后通过CALL/JMP 寄存器 跳到OEP.可以通过右键,search for-> all commands来搜索.

2 堆栈平衡法,也即ESP定律法
类似于函数的开头会保存寄存器,函数结束会释放.(因为函数过程会用到一些寄存器),某些壳会使用pushad指令保存寄存器环境,解密各个区段完毕后,跳往OEP之前,会使用popad指令恢复寄存器环境.
这里还是用上一个例子(见上图),开头是pushad
注意:有些情况下,壳的第一条指令可能不是pushad,但是,有时候会在开头附近,还有时候,不用pushad,而是一个一个的push各个寄存器,例如: push eax,push ebx等等,这些都不是重点,关键在于壳在跳往OEP之前会恢复寄存器环境.



如上图所示,各个寄存器的值被压入了堆栈中,对这些值设置内存断点或者硬件断点(有些壳会检测硬件断点,初学者暂且不谈),当解密例程读取这些值得时候就会中断下来,此时OEP应该就在附近了
在esp上选则follow indump

选中四字节右键->breakpoint->hardwareonaccess->dword

我们断在了popad得下一行
这里要说明一下,现在的壳有很多保护机制,检测机制,有些壳会检测到这种方法,所以大家在脱壳得时候要尝试多种不同的方法
3 使用OD自带得SFX定位OEP
如下,打开debug option

一个是inaccurate,(这个是快的)一个是very slow(慢).
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2020-11-9 11:20
被Golden_Boy编辑
,原因: