Loading... ## 脱壳 --- 查壳-脱壳(查找OEP-使用专用的脱壳工具)-修复 查找OEP 手动脱壳 / 使用专用的脱壳工具 1. PUSHAD (压栈) 代表程序的入口点 2. POPAD (出栈) 代表程序的出口点 与PUSHAD 相对应, 一般找到OEP就在附近 与PUSHAD 相对应, 一般找到OEP就在附近 与PUSHAD 相对应, 一般找到OEP就在附近 3. OEP 程序的入口点,软件加壳就是隐藏了OEP(或者用了假的 OEP/POEP),只要找到程序真正的OEP,就可以进行脱壳 --- #### 单步跟踪法1. 用OD载入点击不分析代码 2. 单步向下跟踪,实现向下跳,也就是说向上的跳不让其实现(通过F4) 3. 遇到程序往回跳(包括循环),我们在下一句代码处按F4(或者右键代码,选择断点--》运行到所选) 4. 绿色线条代表跳转没有实现,红色线条代表跳转已经实现 5. 如果选择刚载入程序,附件会有一个CALL的,我们F7过去不然程序很容易跑飞,这样很快就能到程序的OEP 6. 在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7跟进去 7. 一般很大的跳转(大跨度),比如jmp xxxxx 或者 JF xxxxxx 或者RETN的一般很快就会到程序OEP ### ESP 定律 ESP 是指针寄存器的一种 用于堆栈指针 ESP 为栈指针,用于指向栈的栈顶,而EBP作为帧指针,指向当前活动记录的底部 原理:在保存的堆栈中进行断点,在恢复/堆栈平衡的时候,需要读取、写入操作,这样就可以在这里下断点 --- ESP定律脱壳 (ESP在OD的寄存器中,我们只要在命令行下ESP的硬件访问断点,就会一下来到程序的OEP了!) 1. 开始就点F8,注意观察OD右上角的寄存器中ESP有没有突显(变成红色)。)一般情况下,确切的说我们选择了ESP值得关键语句。 2. 在命令行下:dd XXXXXXXXX(指在当前代码中得ESP地址,或者hr XXX),按回车! 数据窗口中跟随 3. 选中下断电的地址,断点-硬件访-WORD断点 4. 按一下F9运行程序,来到了跳转处,按下F8到达OEP ### 内存镜像法 内存地址: 没有任何的SEH 异常 1. 用OD打开软件 2. 点击选择-调试选项-异常,把里面的忽略全√上!ctrl+f2 重载程序 3. 按ALT+M 打开内存镜像,找到程序得第一个 .rsrc 按下f2下断点,然后按shift+f9 允许断点,接着按alt+m打开内存镜像,找到程序得第一个。rsro,上面得。CODE (也就是004010000处),按F2下断点!然后按SHIFT+F9(或者是在没有异常下按F9)直接到达OEP! ### 一步到达OEP 1. 开始按Ctrl+F 输入popad(只适合少数壳,包括UPX,ASPACK),然后按下F2,F9运行到此处 2. 来到大跳转处,点下F8.到达OEP! ### 模拟跟运行法 1. 模拟跟踪SEH暗桩 2. tc eip<地址 3. tc 是指令 就是让od模拟跟踪的指令 eip 是当前运行的地址 在右侧寄存器可以看到 eip<某个地址 就是限制了 od 的Moines跟踪的范围小于某个地址 就是只在某个地址之前找 4. 模拟跟踪法(不忽略内存异常)【首先忽略所有异常,F9 运行一下,遇到异常,好我们现在试一下不忽略内存异常,再运行,程序运行了, 1. 模拟跟踪法 需要在没有异常的情况下才能完全运用的】 #### 最后一次异常法 在异常中设置有反调试的API,使用最有一次异常调试法进行摆平异常里的反调试。 <span style="color:#DC143C">如果设置之后一路通畅【可能是OD中插件的原因】,那么试一下原生OllDebug。</span> 1. 在调试选项-异常全部忽略(只勾选第一个) 1. ![image.png](http://www.irohane.top/usr/uploads/2021/03/2360563550.png) 2. shift + F9 运行跳过几次异常【主要记录异常次数,弄清楚在哪一个异常清除或者设置了安装(反调试)】 3. 然后重新运行 在程序运行次数 - 1次 【在执行过上一次异常后被反调试了,需要详细分析这个异常】 开始单步跟踪 4. 应该注意左下角的异常状态【注意:在有些有BUG的异常中会乱显示或者不显现,咱也没办法,但也不能说没用】。 ### SFX法 1.设置OD忽略所有异常,异常选项卡都打勾 2.切换SFX选项卡,选择“字节模式跟踪实际入口(速度很慢)”,确定 3.重载程序(如果出现是否“压缩代码”选择 否,OD直接到达OEP) btw:这种方法不能滥用 // 针对压缩壳 对加密壳无用 ### 使用API特征方法 程序运行起来之后 ![image.png](http://www.irohane.top/usr/uploads/2021/03/26326058.png) 右键搜素跨模块调用找到IAT位置 ![image.png](http://www.irohane.top/usr/uploads/2021/03/2839531115.png) FF15 大概率是VS程序 ![image.png](http://www.irohane.top/usr/uploads/2021/03/1898289902.png) 在必要API下断点 Getversion GetSystemTime 在Getversion下断点后run运行注意堆栈看是不是用户区调用的如果不是F9继续找 ![image.png](http://www.irohane.top/usr/uploads/2021/03/3643165265.png) ![image.png](http://www.irohane.top/usr/uploads/2021/03/4208386611.png) # 特征 FF15 大概率VC程序 1. API断点 Getversion GetSystemTime # 花指令 call的地址被加了花指令。所以可以跟进看一下 ![image.png](http://www.irohane.top/usr/uploads/2021/03/627431078.png) 可以看到CALL 被加了花指令 call 3AB0006 ->3AB0005 可以看到jmp这个位置肯定不对劲 指令已经跳过了1字节E9,所以在3AB0005点击小键盘1填充1字节【在OD中可以,在x96DBG只能编辑二进制对E9更改位90NOP】 ![image.png](http://www.irohane.top/usr/uploads/2021/03/3329486463.png) 把花指令填充一些,然后可以基本观察到了有样子的汇编,JMP也可以nop掉。 ![image.png](http://www.irohane.top/usr/uploads/2021/03/612956205.png) 基本填充之后 ![image.png](http://www.irohane.top/usr/uploads/2021/03/1287748758.png) # 使用脚本 脚本的示例: OllySubScript 编写。 ``` // 初始化变量 MOV dwGetApiAddr,0049D5BF //获取程序API的地址,所在代码的下一条指令 MOV dwWriteIATAddr,0049D5F3 //填充到IAT的地址,所在代码的下一条指令相当于覆盖了 MOV dwOEP,0044848D //OEP地址 //初始化环境 BC //清除断点 BPHWC //清除硬件断点 BPMC //清除内存断点 BPHWS dwGetApiAddr,"x" BPHWS dwWriteIATAddr,"x" BPHWS dwOEP,"x" //循环 LOOP0: RUN CMP dwGetApiAddr,eip JNZ CASE1 MOV dwTmp,eax JMP LOOP0 CASE1: CMP dwWriteIATAddr,eip JNZ CASE2 MOV [edi],dwTmp JMP LOOP0 CASE2: CMP dwOEP,eip JNZ LOOP0 MSG "修复成功" ``` ![image.png](http://www.irohane.top/usr/uploads/2021/03/4099260975.png) # 窗口程序 ### 关键API向上查找回调 1. 下相关断点比如 Messagebox 或者 GetDlgItem 【必须可以多次触发】如果只触发一次那就可能没在回调 2. 根据断下位置的堆栈ret处返回上层函数,一层一层往上找,找到类似于回调的函数。 3. 在VS中对照`#define CF_DSPENHMETAFILE 0x008E 类似的消息类型,对其进行分析` 4. 找到我们需要的函数进行修改 最后修改:2021 年 03 月 10 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏