- 第一章 - OD 的各个窗口介绍
- 第二章 - 数值系统
- 第三章 - 寄存器
- 第四章 - 汇编指令
- 第五章 - 数学指令
- 第六章 - 比较和条件跳转
- 第七章 - call ret
- 第八章 - 循环 字符串指令和寻址方式
- 第九章 - 基本概念
- 第十章 - 断点
- 第十一章:硬件断点与条件断点
- 第十二章 - 消息断点
- 第十三章 - 硬编码序列号寻踪-Part1
- 第十四章 - 硬编码序列号寻踪-Part2
- 第十五章 - 硬编码序列号寻踪-Part3
- 第十六章 - 序列号生成算法分析-Part1
- 第十七章 - 序列号生成算法分析-Part2
- 第十八章 - 序列号生成算法分析-Part3
- 第十九章 - OllyDbg 反调试之 IsDebuggerPresent
- 第二十章 - OllyDbg 反调试之检测 OD 进程名
- 第二十一章 - OllyDbg 反调试之检测 OD 进程名,窗口类名,窗口标题名
- 第二十二章 - OllyDbg 反调试之 UnhandledExceptionFilter,ZwQueryInformationProcess
- 第二十三章 - OllyDbg 反调试之 ProcessHeap,NTGlobalFlag,OutputDebugStringA
- 第二十四章 - OllyDbg 反调试之综合 CrackMe
- 第二十五章 - 异常处理
- 第二十六章 - Visual Basic 程序的破解-Part1
- 第二十七章 - Visual Basic 程序的破解-Part2
- 第二十八章 - Visual Basic 程序的破解-Part3
- 第二十九章 - P-CODE-Part1
- 第三十章 - P-CODE-Part2
- 第三十一章 - 脱壳简介
- 第三十二章 - OEP 寻踪
- 第三十三章 - 神马是 IAT 如何修复
- 第三十四章 - 手脱 UPX,修复 IAT
- 第三十五章 - 手脱 ASPack V2.12
- 第三十六章 - IAT 重定向
- 第三十七章 - 论 IAT 重定向之修复
- 第三十八章 - 手脱 Yoda's Protector v1.3(Yoda's Crypter)
- 第三十九章 - 神马是 stolen bytes
- 第四十章 - OllyDbg 脚本的编写
- 第四十一章 - 神马是 AntiDump
- 第四十二章 - ACProtect V1.09 脱壳(寻找 OEP 绕过硬件断点的检测 修复 Stolen code)
- 第四十三章 - ACProtect V1.09 脱壳(编写脚本修复 IAT)
- 第四十四章 - ACProtect V1.09 脱壳(修复 AntiDump)
- 第四十五章补充章节-ReCrypt v0.80 脱壳(续)
- 第四十六章 - Patrick 的 CrackMe-Part1
- 第四十七章 - Patrick 的 CrackMe-Part2
- 第四十八章 - PeSpin V1.3.04 脱壳-Part1
- 第四十九章 - PeSpin V1.3.04 脱壳-Part2
- 第五十章 - 再谈 ReCrypt v.0.80 脱壳(调戏 OutputDebugString)
- 第五十一章 - ASProtect v2.3.04.26 脱壳-Part1
- 第五十二章 - ASProtect v2.3.04.26 脱壳-Part2
- 第五十三章 - TPPpack 脱壳
- 第五十四章 - EXECryptor v2.2.50.a 脱壳-Part1
- 第五十五章 - ExeCryptor v2.2.50.a-Part2
- 第五十六章 - EXECryptor v2.2.50.b 脱壳
- 第五十七章 - ExeCryptor v2.2.50.c/d/e/f/g 脱壳
- 第五十八章 - ExeCryptor v2.2.50
第五十章 - 再谈 ReCrypt v.0.80 脱壳(调戏 OutputDebugString)
本章我们回头再来看看 Recrypt v0.80 这个壳,给大家介绍了 Patrick 和 PeSpin 这两款壳以后,再回头来看 Recrypt 这款壳,可以说是小菜一碟了。本章我会给大家介绍 OllyAdvanced 这款反反调试插件的使用,首先我们用专门定位 OEP 的那款来 OD 加载 UnPackMe_ReCrypt0.80.exe。
我们来配置一下这个插件,这个插件提供了一个 Bugfixes(bug 修复选项卡),其中就有修复 NumOfRva Bug 这一项。
我们直接运行起来,看看会发生什么。
这里我们可以看到 UnPackMe_ReCrypt0.80 区段显示都是正常的,我们剔除掉 OllyAdvanced 这个插件看看又会是怎么样的呢。
这里我们可以看到没有 OllyAdvanced 插件的话,还没有到达 OEP 就报错了。我们来看看区段,会发现主模块 UnPackMe_ReCrypt0.80 只显示了一个区段。这样的话我们只能通过 PEEditor 来查看代码区的起始位置以及大小,然后手动给代码段所在区域设置内存访问断点来定位 OEP 了,但是有了 OllyAdvanced 这个插件,这一切都可以省略了,嘿嘿。
下面我们直接运行起来。
嘿嘿,可以看到弹出了一个错误框,根据提示信息可以看出 OD 遇到了无法处理的异常。我们打开日志窗口看看出错的日志信息。
大家注意到这个 Debug string:字符串没有,说明该程序调用了 OutputDebugStringA 这个 API 函数来输出调用信息。OutputDebugString 函数用于向调试器发送一个格式化的字符串,Ollydbg 会在底端显示相应的信息。OllyDbg 存在格式化字符串溢出漏洞,非常严重,轻则崩溃,重则执行任意代码。这个漏洞是由于 Ollydbg 对传递给 kernel32!OutputDebugString() 的字符串参数过滤不严导致的,它只对参数进行那个长度检查,只接受 255 个字节,但没对参数进行检查,所以导致缓冲区溢出。虽然 OllyAdvanced 以及其他一些 OD 插件提供了对 OutputDebugString 函数的修复功能,但是我们这里还是无法正常运行。我们给 OutputDebugStringA 这个 API 函数下个断点一探究竟。
这里由于我不想给每次都手动在命令栏中一个字母一个字母的输入 API 函数的名称,所以这里我使用网上的朋友写的一款插件来完成这个任务,这个插件的名字叫做+BP-Olly。有了这个插件,我们只需要通过一次简单的按钮单击就可以完成对常见 API 函数的断点设置。
我们打开 BP 这个选项卡发现并没有 OutputDebugStringA 这个 API 函数,怎么办呢?不要紧,该插件有自定义功能,我们可以通过单击 P(Personal:个人的) 按钮将 OutputDebugStringA 这个 API 函数添加到列表当中。
我们单击 Personalizar 按钮,左边就多显示处一个对话框,我们输入 BP OutputDebugStringA,接着单击 Guardar(添加) 按钮。
请注意,API 函数的名称大小写要正确。下面我们再次单击 P 按钮。
这里我们可以看到 BP OutputDebugStringA 这个按钮就出现了,我们只需要单击一下 BP OutputDebugStringA 这个按钮,就可以给 OutputDebugStringA 这个 API 函数设置上断点。是不是很方便。嘿嘿。(PS:其实国内也有很多 OD DIY 的版本也提供了这个功能,譬如说吾爱破解的 OD)
接着我们运行起来,会发现还是会报错。就是说简单的给 OutputDebugStringA 这个 API 函数设置 INT3 断点并不起作用。所以这里我们重启 OD,接着在命令栏中输入 HE OutputDebugStringA 给该 API 函数设置一个硬件执行断点试试看。
删除掉刚刚设置的 BP 断点,接着运行起来。(PS:这里下 INT3 断点会报错因为反反调试插件之间存在冲突)
断了下来,我们执行到返回。
返回到了这里。
这里我们可以看到将 EAX 的值与零做比较,看看会发生什么。
这里我们可以看到 EAX 的值不等于零,接着跳转到下面将 EAX 的值与栈顶指针指向的内容相加。
相加以后栈顶的内容变成了:
我们继续往下跟踪,会发现下一条指令是 RET,那么相加到栈顶的内容就是返回地址了。
534DF0 这个地址并不存在,所以我们直接运行起来会抛出异常,而这个异常是调试器无法处理的,所以就报错了。
好了,报错的具体原因我们已经弄明白了,下面我们来修复它。
我们重启 OD,运行起来,断在了 OutputDebugStringA 处,执行到返回,接着直接将 EAX 的值修改为 0。
下面这个条件跳转就不会成立了,接下来 EAX 加 1,现在 EAX 的值为 1,下来继续将栈顶指针指向的内容加上 EAX,也就是加 1。
接着就是调用 RET 指令返回了。
现在这个返回地址是 405115,这个地址是存在的,也就不会报错了。现在我们直接给主模块的代码段设置内存访问断点(这个 OD 是 Patch 过的,内存访问断点只是单单执行的时候才会断点来,读取或者写入并不会断下来,这样就方便我们定位 OEP 了,大家应该还记得吧),运行起来。
不一会儿就断下了 OEP 处。
这里我们就断在了 OEP 处。
我们单击鼠标右键选择 Search for-All intermodular callsd 搜索所有的 API 函数调用处。
我们可以看到只有少量的 API 函数调用,IAT 如下:
这里我们可以看到 IAT 的起始地址为 402000,结束地址为 40201C。也就是说 IAT 的起始地址的 RVA 为 2000,长度为 1C。OEP 的 RVA 为 1000,下面我们将其 DUMP 出来,接着用 IMP REC 来修复其 IAT。
我们打开 IMP REC。
填上 OEP 的 RVA,IAT 的 RVA,大小之后单击 Get Imports 获取导入表,接着单击 Fix Dump 修复刚刚 dump 出来的文件。
我们直接运行修复后的文件。
嘿嘿,搞定。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论