[安全攻防进阶篇] 七.逆向分析实战:OllyDbg破解CrackMe03及动态调试技巧
1. OllyDbg动态调试基础回顾在开始CrackMe03的实战之前我们先快速回顾下OllyDbg的核心功能。作为逆向工程领域的瑞士军刀OllyDbg的界面主要分为五个功能区域左上角的反汇编窗口会实时显示CPU执行的指令流右上角的寄存器窗口反映着各个寄存器的当前状态中间的信息窗口会提示当前指令的关联信息下方的数据窗口可以查看任意内存地址的内容而堆栈窗口则展示了函数调用时的栈帧变化。调试过程中最常用的几个快捷键需要烂熟于心F2在光标位置设置/取消断点就像在代码里埋下陷阱F9让程序全速运行直到触发断点或异常F8单步步过执行遇到函数调用时不进入F7单步步入执行会深入到每个CALL内部CtrlF9执行到当前函数的返回指令AltF9快速从系统API返回到用户代码提示调试时建议把数据窗口调整为HEXASCII双栏显示这样既能观察二进制值又能识别可能的字符串2. CrackMe03初步分析这次的目标程序是个典型的序列号验证型CrackMe运行后会出现用户名和注册码的输入框。随意输入测试数据点击验证程序会弹出Invalid Serial的错误提示。按照逆向分析的常规流程我们首先需要确认几个关键信息使用PEiD检查发现程序没有加壳是用VC 6.0编译的32位程序字符串搜索中除了错误提示还发现了Congratulations!的成功提示程序没有网络连接行为验证逻辑完全在本地完成在OllyDbg中加载程序后我们先在所有参考文本字符串中找到错误提示Invalid Serial双击跳转到反汇编位置。这里可以看到程序在比较后有一个关键的JE跳转指令当验证失败时会跳转到错误提示分支。我们在JE指令上按F2设下断点准备开始动态分析。3. 关键验证逻辑追踪重新运行程序并触发验证流程后OllyDbg会在我们设置的断点处暂停。此时观察寄存器窗口发现EAX和EDX寄存器中分别保存着两组数据EAX: 我们输入的假注册码123456EDX: 一段看似随机的字符串5G8H2K继续按F8单步执行会发现程序在调用一个位于0x00401000的关键CALL。这个函数内部进行了多次位移和异或运算最终生成的结果会与我们的输入进行比较。为了弄清算法逻辑我们需要深入这个CALL进行分析。在CALL指令处按F7进入函数内部可以看到如下关键代码片段00401020 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP8] ; 取用户名指针 00401023 |. 0FB600 MOVZX EAX,BYTE PTR DS:[EAX] ; 取首字母ASCII 00401026 |. C1E0 04 SHL EAX,4 ; 左移4位 00401029 |. 0345 0C ADD EAX,DWORD PTR SS:[EBPC] ; 加上固定值0x1234 0040102C |. 35 78563412 XOR EAX,12345678 ; 与魔数异或 00401031 |. 8B4D 08 MOV ECX,DWORD PTR SS:[EBP8] ; 再次取用户名 00401034 |. 0FB649 01 MOVZX ECX,BYTE PTR DS:[ECX1] ; 取第二个字母 00401038 |. C1E1 08 SHL ECX,8 ; 左移8位 0040103B |. 33C1 XOR EAX,ECX ; 二次异或 0040103D |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX ; 保存结果4. 注册算法还原通过动态调试观察各个寄存器的变化我们可以还原出注册码的生成算法。假设用户名为test其计算过程如下取用户名首字母t的ASCII值0x74左移4位得到0x740加上固定值0x1234得到0x1974与魔数0x12345678异或得到0x12344F0C取第二个字母e的ASCII值0x65左移8位得到0x6500与之前结果异或得到最终密钥0x12340A0C用Python实现这个算法如下def generate_key(username): first_char ord(username[0]) second_char ord(username[1]) if len(username) 1 else 0 key (first_char 4) 0x1234 key ^ 0x12345678 key ^ (second_char 8) return f{key:X} # 转为大写十六进制5. 高级调试技巧实战在分析过程中有几个实用技巧值得特别说明条件断点设置在循环验证的场景下可以右键断点选择Condition...设置如[EAX]0x12345678的条件只有当EAX值为特定数值时才中断。内存断点监控当发现程序会读取某块关键内存时可以在数据窗口选中该内存区域右键选择Breakpoint→Memory on access。API调用追踪在名称窗口中可以对关键API如GetWindowTextA设断监控程序获取用户输入的过程。数据跟随分析在寄存器或数据窗口的值上右键选择Follow in dump可以持续追踪该数据在内存中的变化。6. 反反调试技巧某些CrackMe会检测调试器存在常见的手段包括检查父进程是否为调试器调用IsDebuggerPresent API检测硬件断点DR0-DR3计算代码段校验和遇到这类情况时可以使用插件隐藏调试器特征在API调用前修改返回值为0直接NOP掉检测代码使用虚拟机进行分析7. 验证结果与总结使用我们还原的算法为用户名test生成的注册码是12340A0C。在程序中输入测试Username: test Serial: 12340A0C点击验证按钮后成功弹出Congratulations!对话框。通过这个案例我们不仅掌握了OllyDbg的动态调试技巧还学会了如何分析复杂的验证算法。建议大家在调试时养成记录寄存器变化的习惯这对理解程序逻辑非常有帮助。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2441801.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!