壳¶
- 压缩壳
- 加密壳
UPX壳¶
壳的加载¶
- 保存入口点的参数
- 加载程序初始化时保存各个寄存器的值
- 外壳程序执行完毕后, 恢复寄存器的值
- 跳到源程序执行
- 获取所需的函数API
- 一般壳的导入表中只有GetProcAddress, GetModuleHandle和LoadLibrary
- 如果需要其他的API函数, 则通过
LoadLibraryA(w)
或者是LoadLibraryExA(w)
将dll文件映射到调用进程的地址空间中 - 如果
DLL
文件已经映射到调用进程的地址空间中, 就可以调用GetModleHandleA(w)
函数获得DLL模块的句柄 - 一旦DLL模块被加载, 就可以调用
GetProcAddress
获得输入函数的地址
- 解密各区块的数据
- 跳回原程序的入口点
- 先恢复原PE文件的IAT,处理重定位项
- 加壳的时候, 外壳自己构造了一个输入表, 重新对每一个dll引入的函数获取地址, 填写到IAT表中
脱壳¶
- 自动脱壳
- 正常脱
- 改待修改字如CTF...为UPX\
- 可以通过DIE等工具看一下哪些被修改了, imhex有文件对功能, 也可以使用
- imhex双击修改字节
- 手脱
- 查壳
- 寻找OEP
- Dump内存
- 输入表重建(IAT)
- 关闭程序重定位
寻找OEP¶
单步跟踪¶
- F8单步向下
- 大循环使用F4来跳过
- 壳代码的入口点是一个近call, 不要跳过, 跟入
- 大幅度跳转的jmp指令, 都有可能跳到了原程序的入口点
ESP定律¶
通过堆栈平衡来快速的找到OEP 1. 程序刚开始push 2. 将寄存器压栈后就在rsp/esp寄存器所在处设置硬件访问断点 3. 运行程序, 触发断点
修复IAT¶
X64的自带插件
去重定位¶
- File Header的Charateristics
- Optional Header的DllCharateristics
- 去掉Relocation info