1625-5 王子昂 总结《2018年2月19日》 【连续第506天总结】
A. 脱壳技术(2)寻找OEP
B.
寻找OEP
外壳保护的程序运行时,首先会执行外壳
将原程序解密到内存中,再将控制权转交给原程序来正常执行
无论是脱壳恢复原程序还是调试,都需要找到原程序的入口点,即OEP
找OEP有以下几种方法
- 根据跨段指令
大多数PE加壳程序会在被加密的程序中加上一个或多个区块,外壳将原程序代码解密到一个单独的区块中,然后jmp到该区块中执行
因此可以注意较远的、跨段的jmp指令 - 用内存访问断点
有的壳会将自身保存在其他区段中,而将目标区段仍然命名为.text;也有的壳会将所有区段重命名(例如upx)
OD可以对整个区段设断(原理应该是设置内存属性为不可执行,然后捕获异常断下),如果有.text可以直接下,没有的话也可以逐个尝试,一般区段在2-4个 - 根据堆栈平衡原理
俗称ESP定律
由于壳程序解密原程序前后的环境(寄存器、堆栈等)需要一致,使得原程序可以正常启动,因此壳程序通常会使用pushad/hpopad、pushfd/popfd等指令来保存和恢复,此时就可以等待push后对堆栈下访问断点
断下来的时候显然就是在pop恢复环境了,之后再运行几条指令即可找到OEP了 根据编译语言特点
各类语言编译的文件入口点都有自己的特点(毕竟入口点是由编译器批量生成的,跟编译出的程序无关)
例如VC++6.0默认的入口点代码大概有4个版本,分别对应不同的启动函数- 处理ANSI字符的GUI版本
WinMainCRTStartup - 处理ANSI字符的CUI版本
mainCRTStartup - 处理Unicode字符的GUI版本
wWinMainCRTStartup - 处理Unicode字符的CUI版本
wmainCRTStartup
值得注意的是,开发人员可以自定义启动源代码,此时的入口点代码就不符合特点了
- 处理ANSI字符的GUI版本
C. 明日计划
脱壳技术(3)