- 第一章 - 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
第十八章 - 序列号生成算法分析-Part3
本章,我们将讨论 Stzwei’em 提供的 CrackMe,名字叫”crackme_4stz”。
用 OD 加载它。
我们断在了入口点处,我们首先看一下 API 函数列表。
程序中使用的字符串列表如下:
貌似没有什么我们感兴趣的字符串,我们再来看看 API 函数列表。
哇,这么多...好吧,我们运行起来,出现了主窗口,可以输入序列号。
我们可以看到没有注册按钮,我们随便输入一个用户名。
我们需要给 TranslateMessage 这个 API 函数设置条件记录断点,首先给该函数设置一个普通断点。
我们回到 CrackMe 的主窗口,继续编辑断点的条件。
如果你不知道要拦截什么的消息的话,那就先单击工具栏中 W 按钮打开窗口列表吧。
我们找到 CrackMe 的主窗口这行,在上面单击鼠标右键。
出现了消息断点窗口,我们打开 Messages 消息下拉框。
我们找到 WM_KEYUP 消息。
我们可以看到 WM_KEYUP 的值为 101,所以我们关闭该窗口,打开 TranslateMessage 断点所对应的条件记录断点窗口。
这里,我们设置条件为 MSG == 101(注意是双等号),如果我们没有找到这个值的话,我们写成 MSG== WM_KEYUP 同样可以。
但是我更喜欢写成 MSG==101 这样形式,按照的自己的习惯来就行了。
单击 OK 以后 TranslateMessage 函数入口处的断点就会变成粉红色。
我们运行起来,输入错误序列号的第一个字母。
马上就触发刚刚设置的条件断点了。
我们可以看到堆栈中 TranslateMessage 的参数情况,12FF78 指向的结构中保存 key 值等于 39(十六进制),该 ASCII 值正好对应的得我们刚刚输入的字符’9’。
我们在该参数上面单击鼠标右键选择-Follow in Dump 在数据窗口中定位到内存单元。
我们可能会想到对该字节设置内存访问断点,让程序在读取该字节与正确的序列号进行比较的时候断下来,但是该 CrackMe 是个 Delphi 的程序,Delphi 程序是经过深度封装的程序,可能在与正确的序列号进行比较之前,12FF80 对应内存单元中序列号已经经过了很多次的内存的中拷贝了,所以直接对该字节设置内存访问断点是不可取的。我们可以采用上一章使用的方法,先在内存中搜索我们输入的序列号,定位到以后再对区域设置内存访问断点可能更方便一些。
运行起来。
我们输入 9898,然后回到 OD 中,通过单击工具栏中 M 按钮查看所有内存。
单击鼠标右键选择-Search。
查找 9898。
我们继续 CTRL+L 查看看看还有没有其他内存中有该字符串。
直到 OD 底部显示黄色的”Item not found”的字样,这个区段就查找完毕了,我们继续回到内存列表窗口中。
我们再次 CTRL+L。
找到了该区段的第一处,我们继续 CTRL+L 看该区段还有没有其他地方有。
继续查找没有了,我们可以看到上方有一个 418507 可能是正确的序列号,我们对我们输入的错误序列号设置内存访问断点,看看程序是否会取该序列号来进行比较。
运行起来。
这里,我们可以看到正在拷贝我们输入的用户名。
我们可以看到错误序列号的内存单元将被覆盖为我们输入的用户名。那我们可以对下面可能是正确序列号的字符串设置内存访问断点。
可以看到断下来了,正在进行比较。
这里,我们可以看到,ESI,EDI 分别指向了正确和错误的序列号。
每次比较四个字节,我们验证一下该序列号是否正确。
提示序列号正确。
可以看到,这个的 CrackMe 还是有一点小难度的,不过我们还是可以在一个合适的时间点跟踪到我们输入的错误序列号的位置,并且通过设置内存访问断点来定位到正确的序列号。
另一种方法可以从内存写入断点切入。
我们输入第 5 个字节。
我们对下一个字节可能会写入的内存单元设置内存写入断点。
为了输入下一个字符,我们运行起来。
这里可能是正确的序列号。
继续运行。
断在了拷贝错误序列号处,我们可以继续设置内存断点定位到序列号比较代码处。
可以看到,这种方式稍微复杂一点。
好了,留下 CrueHead’a 的第二个 CrackMe 给大家练习。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论