ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

重做Lena教程tutorial06:从OllyDbg动态分析到注册机实现的逆向基本功

重做Lena教程tutorial06:从OllyDbg动态分析到注册机实现的逆向基本功 前几天整理移动硬盘翻出一个很老的文件夹里面躺着整套tuts4you时期的lena151教程整整151课的OllyDbg录像和配套Crackme。想当年就是靠这套教程我才从连断点是什么都不知道的小白一步步走进逆向这个坑。这次我特意把tutorial06调出来重做了一遍因为第六课在整个系列里是个标志性的转折点——前五课还在手把手教你认识调试器从这一课开始你就得自己动手把一条完整的注册验证链拆开。这篇文章就当作一份tutorial06的复盘笔记来写环境怎么搭、关键代码怎么定位、拿到判断逻辑后是直接改跳转还是老老实实写注册机以及每个环节里我踩过的坑。如果你刚接触逆向或者卡在“跟着视频能做出来、自己拿到新程序就懵”的阶段这篇应该能帮你把零散的调试技巧串成一条完整思路。1. 收藏夹里的老经典为什么我又把tutorial06翻了出来1.1 那个流传了十几年的“151课”到底在教什么Crackme是专门给安全爱好者练习逆向的小程序它的唯一目的就是被分析、被注册、被patch不涉及任何真实商业软件的破解行为所以拿它练手是安全且健康的学习路径。tuts4you论坛上的这位Lena作者把这条路径做成了系统课程从OllyDbg怎么打开程序、各个窗口是什么意思讲起一路覆盖到断点、寄存器、标志位、消息循环再到壳、反调试、内存补丁和注册机编写。每一课配一个或多个Crackme看完视频自己动手练练完再做下一个。这套内容放到今天看依然是“以练带学”的教科书级示范。为什么这么多年过去我还会推荐它因为工具可以换但方法论没有变。OllyDbg 1.10的界面是2004年前后的样子x64dbg已经成了新一代主流调试器可“跑起来看行为、下断点定位代码、分析判断逻辑”这条链路从来没变过。你今天的tutorial06练的每一个动作放到任何一个当代CTF逆向题、任何一个恶意样本分析场景里都还是同样的底层思路。1.2 第六课的位置从“看懂”到“会做”的过渡前几课的练习基本是“认识工具”——加载程序、单步、F8和F7区别、看寄存器变化难度更像在教室里跟着老师念课本。到了tutorial06训练目标突然变了现在给你一个只有注册验证功能的Crackme你需要独立完成“定位→分析→收尾”这个闭环。具体拆开就是四点在调试器里把程序跑起来且能正常触发它的错误提示通过程序运行时的某个行为比如错误弹窗反向找到对应的代码区域读懂那段代码里的验证判断到底在比什么要么修改跳转让程序放行要么算出有效序列号。这四步在今天依然是逆向分析的基本功。很多人学了一大堆“技巧”但拿到新程序就懵本质就是第二步和第三步没形成肌肉记忆。tutorial06的价值恰恰在于它在你刚学会用工具的时候逼你把“程序行为”和“代码位置”这两张地图连起来。这一课练熟了后面学脱壳、学反调试、学混淆对抗都只是在这个基础上加料。2. 动手前先把家伙准备好虚拟机、OllyDbg与配套工具2.1 为什么非要在虚拟机里跑Crackme我知道很多人图省事直接在物理机上把Crackme拖进OllyDbg就开工。我的建议是别省这一步。老Crackme基本都是32位程序在Win10、Win11上可能出现兼容性问题比如起不来、界面错乱、按钮点不动浪费一堆时间排查环境问题。更重要的是调试器和程序在动态分析时会产生很多奇奇怪怪的交互如果是在一个干净的虚拟机里出了问题直接快照恢复重来完全不用心疼。虚拟机选VMware或者VirtualBox都行系统建议Windows XP SP3或者Windows 7 32位内存给1到2GB足够。装好系统后拍一个干净快照以后每次练习前恢复一下保证环境一直处于“初始状态”。这个习惯不仅练Crackme有用后面分析真实样本时更是保命技能。2.2 OllyDbg版本选择与几个关键设置OllyDbg的版本选择有个很现实的问题教程截图是哪个版本你就用哪个版本否则菜单位置对不上会非常痛苦。lena教程用的是OllyDbg 1.10我这次复盘也用的1.10。它的界面旧、插件老、对64位程序完全无能为力但它足够经典而且网上绝大多数老教程和讨论都是围绕它展开的。如果你不想入这个“老坑”直接上x64dbg也可以核心操作逻辑相同只是部分菜单名称和快捷键有差异。不管用哪个版本上手前先把这几件事做了在Debugging Settings的Exceptions页面把“Ignore all exceptions”勾上。很多Crackme会故意触发异常来干扰调试忽略掉它们能让流程顺畅得多打开命令行窗口熟悉一下bp、bc、dd这些基础命令。后面下消息框断点会用到记住一个关键认知OllyDbg加载程序后默认停在“系统断点”这时候程序还没真正运行。不要在这个状态下做任何分析先按F9让程序跑起来再说。2.3 备选工具IDA、PEiD、Cheat Engine各管哪一段工具不是越多越好但每个工具适合解决的环节确实不一样。我按自己这次复盘的实用度列了个表工具主要用途什么时候用OllyDbg / x64dbg动态调试下断点、单步、看寄存器和内存完成90%的定位工作必备IDA Free静态分析生成反汇编和伪代码快速浏览程序逻辑程序比较长、动态跟踪太繁琐时PEiD / Detect It Easy查壳和编译器特征程序运行时明显不自然怀疑加壳时Cheat Engine内存扫描定位变量和数值变化想从“数据变化”角度分析时比如游戏类目标新手阶段其实先玩熟OllyDbg就够了其他工具用到再学。提Cheat Engine是因为现在很多人是搜“cheat engine tutorial games”入门的那个工具解决的是“数据在哪里变化”的问题而OD解决的是“哪段代码改写了数据”的问题两者本质上是互补关系后面6.1节我会展开说。3. 一次完整的动态分析从运行程序到定位关键判断3.1 先当用户玩三分钟拿到一个Crackme第一件事不是打开OD而是把它当成一个普通软件先“玩”一遍。打开窗口看看界面上有几个输入框、按钮上写的是什么文字、有没有多余的功能。然后随便填一个用户名、随便填一个序列号点击验证盯着程序给出的反应。这一步别嫌浪费时间。你需要在动手调试前知道两件事程序的正常流程长什么样以及它报错时到底说了什么话。错误弹窗里的那句原文就是后面用字符串搜索定位代码的关键线索。比如弹窗写着“The serial is wrong, try again.”那么“wrong”或“try again”就是你搜索的锚点。如果跳过这一步直接上调试器你连“正确流程”和“错误流程”的分界点在哪都不知道分析起来会非常被动。3.2 字符串参考OllyDbg里“一键直达”关键代码的方法当程序运行起来、你也记住了错误提示之后重头戏就开始。用OllyDbg加载Crackme按F9让程序跑起来——注意是跑到程序自己的入口和消息循环不是停在系统断点。然后在CPU窗口右键选择“Search for”→“All referenced text strings”中文版叫“所有被引用文本字符串”这时候OD会列出程序里所有被引用到的字符串常量。在搜索框里输入你刚才记下的错误提示关键词定位到那条字符串双击跳转到引用位置。在这个位置往上翻几行你大概率会看到一段这样的结构00401000 push 0 ; 参数控件ID获取输入内容 00401002 call GetDlgItemTextA 00401007 lea eax, [buffer] 0040100A call 00401150 ; 内部函数计算注册码 0040100F cmp eax, edx ; 将计算结果与用户输入比较 00401011 jnz short 00401020 ; 不相等就跳到失败分支 00401013 mov eax, [successMsg] ; 相等则显示成功 00401018 call MessageBoxA说明一下这是一段按tutorial06难度级别最常见的形态写的示意代码具体某个Crackme的指令和地址肯定不完全一样但结构高度相似一个内部计算函数、一条cmp比较指令、一条条件跳转决定走成功分支还是失败分支。看到cmp和它下面的jz/jnz你基本就站在整个验证逻辑的心脏位置了。3.3 消息框断点没有字符串可搜时的兜底方案字符串参考好使但不是每次都好使。某些Crackme会把关键字符串简单加密一下或者用动态拼接的方式生成错误信息导致OD的字符串列表里啥也搜不到。这时候消息框断点就派上用场了。在OllyDbg命令行窗口输入bp MessageBoxA回车如果程序用的是宽字符接口再补一条bp MessageBoxW两个都下上不亏。按F9继续运行切回Crackme窗口随便输入假码点验证。程序一弹窗OD就会立刻断在系统DLL里的MessageBoxA入口CPU窗口显示的是一大堆user32.dll里的代码。新手到这里特别容易慌怎么断在系统里了别慌。这时候看堆栈窗口栈顶附近有一行“返回到 xxx”后面跟着的地址就是程序领空里调用MessageBoxA的地方。右键选择“反汇编窗口中跟随”Follow in DisassemblerOD会带你跳回Crackme自己的代码而错误弹窗的触发位置就在附近。往上翻你又会看到cmp和跳转——和字符串参考的最终结果殊途同归。3.4 与关键跳转面对面确认判断逻辑的验证方法找到cmp和条件跳转之后先别急着改。正确做法是给那条跳转指令下个断点选中指令按F2重新运行程序。输入错误的序列号断点命中后看这条跳转是不是跑向了失败分支然后再次运行在断点处手动修改ZF标志位寄存器窗口里双击ZF的值或者直接修改跳转条件看程序是不是拐进了成功分支。两次结果对比你就能确认这条指令确实是决定生死的那个关键跳转。同时认真看比较指令两边的数据。cmp eax, edx里eax来自前面那个内部计算函数的返回值edx来自用户输入的序列号。如果你在断点处观察eax和edx的具体值很有意思的情况会出现eax可能是一个固定值也可能随用户名变化而变化。搞清楚这一点你就摸到了注册算法的门槛这正是下一章要讲的“注册机路线”的起点。4. 两条收尾路线直接patch与注册机实现4.1 爆破路线一条跳转指令的修改与保存当你确认了关键跳转最简单的收尾方式就是改它。我习惯把这种方式叫“爆破”它不是贬义词而是一种快速验证思路的手段。比如原指令是jnz short 00401020意思是“结果不相等就跳到失败”你选中这行按空格把它改成jmp short 00401013让程序不管三七二十一直接进成功分支。也可以更精细一点把jnz改成jz这样只有输入错误码时才放行输入正确码反而失败——但没人会这么跟自己过不去实战中直接jmp最省事。如果担心改动太大影响程序结构也可以把这条跳转指令整体填成NOP空指令让条件判断形同虚设程序自然顺着走成功分支。确认跑通之后要保存。右键选中修改过的指令选择“Copy to executable”→“All modifications”然后保存成新文件。推荐保存成不同文件名比如原文件是crackme6.exe就保存为crackme6_patched.exe方便和原始文件对照。保存完再跑一遍确认patch不是只在调试器里生效。必须提醒一点有些Crackme不止一个验证点比如按钮验证是一处菜单栏验证是另一处甚至还有定时弹窗。改完一处后要回到程序里把其他入口都测一遍漏掉任何一个都会让你误以为patch失败了。4.2 算法路线从比较指令反推注册码的计算过程爆破快速但学习的角度来说我更希望你至少花一半时间走算法路线。做法是回到那个内部计算函数前面示意代码里的call 00401150在call那一行按F7单步进入一行一行读汇编搞清楚它到底对用户名做了什么运算。这类入门级Crackme的常见算法不过那几种用户名字符ASCII码累加、和某个固定常数异或、按字符位置加权求和、查表替换。只要耐下心来把遇到的每条指令都弄懂是什么意思算法就藏在里面。看懂之后用Python之类的高级语言把同样的逻辑重写一遍就是一个注册机。写出来大概是这种感觉# 示意代码假设算法是“用户名每个字符ASCII码相加乘以0x1234再加上0x5678” def calc_serial(name): s sum(ord(c) for c in name) return (s * 0x1234 0x5678) 0xFFFFFFFF name input(input name: ) serial calc_serial(name) print(valid serial:, serial)注意这是示意不是某个具体Crackme的真实算法。我要强调的是这个“读懂逻辑→用程序重现”的过程。练完这一课如果你能不看任何题解靠自己的逆向和重写能力算出正确序列号输入进去看到成功提示那种成就感比爆破大得多。4.3 两条路线的取舍与练习建议爆破快注册机慢爆破省事注册机长本事。我给新手一个具体建议第一遍做练习的时候先用爆破把所有验证点找全、确认自己已经完整理解了程序的控制流第二遍再从头走算法路线把注册机写出来。两遍都跑通这个练习才算真正吃透。以后遇到真实分析场景比如你面对的是一个恶意样本的授权校验逻辑直接patch可能连文件完整性校验都过不去那时候唯一可靠的方案就是理解算法、算出合法输入。所以这项功课建议从一开始就认真练。5. 第六课之外的实战教训几个绕不过去的坑5.1 字符串搜索搜不到先想想编码问题字符串参考用多了一定会遇到搜不到的情况。除了程序故意加密字符串之外最多见的原因是编码不对。老外写的Crackme大多是普通ASCII或Unicode在OD的字符串列表里一搜就中。但你遇到中文Crackme或者汉化版程序时关键提示经常是GBK编码的中文比如“注册码错误”OD的默认ASCII搜索根本覆盖不到。我的经验是优先搜英文关键词。就算程序是中文界面很多Crackme也会藏一个“incorrect”“failed”“try again”之类的英文常量。实在搜不到不要死磕字符串直接上消息框断点见招拆招比在编码泥潭里挣扎高效得多。5.2 断点断到系统DLL里怎么一步步找回来消息框断点触发后断在user32.dll或kernelbase.dll里面这是新手最常见的迷路现场。CPU窗口里全是系统代码、不认识、不知所措。这里就一个原则不要看代码看堆栈。打开堆栈窗口找到“返回到”那一行——通常它显示的是一个带地址的调用方信息。右键选择“反汇编窗口中跟随”OD就会带你去到程序领空。如果这招不惯用还有一个办法按CtrlF9也就是“执行到返回”OD会自动运行到你刚才那个API函数的返回处往往就是程序代码里紧跟调用指令的那一行。这时候再看上下文整个逻辑就串起来了。5.3 反调试现象一运行就退出不一定是你操作错了练到后面一定会碰到这种怪事同一个Crackme直接在资源管理器里双击运行一切正常但用OD加载后按F9程序要么毫无反应要么瞬间退出。先别怀疑是自己哪里配置错了这很可能是程序调用了IsDebuggerPresent之类的反调试API检测到了调试器存在主动退出。入门阶段遇到这种情况简单做法是给IsDebuggerPresent下断点程序调用它时让它返回0骗过检测或者用StrongOD这类插件做隐藏调试器处理。tutorial06阶段的练习基本不会涉及反调试这里提出来是提前给你打预防针——这门课往后十几课开始壳和反调试会成为主角到时候这个坑会反复出现。5.4 另一个常见失误系统断点状态下乱搜字符串还有一个我见过无数新手踩的坑刚把程序拖进OD停在系统断点就急急忙忙右键搜字符串结果列表空的心里咯噔一下“这程序是不是有问题”。不是程序有问题是你操作顺序不对。系统断点时程序还没加载完自己的代码和数据字符串常量自然还没被解析出来。正确顺序永远是先F9运行到程序正常运行状态哪怕它停在某个等待输入的状态然后再做字符串参考、再下断点。这也是我前面反复强调“先跑起来再说”的原因。调试器的很多功能前提条件都是“程序已经跑起来了”。6. 从Crackme练出来的本事能用在哪些正经地方6.1 同一个套路换个目标还能怎么用这套“行为→代码→数据”的定位方法论绝不只是为了解Crackme题。打CTF的时候逆向题拿到一个二进制第一反应永远是“跑一下看它要什么输入、报什么错”然后顺着行为找关键校验函数这跟tutorial06的流程一模一样。分析恶意样本的时候你关心的不再是注册验证而是它调了哪些敏感API、在哪个分支决定是否下载下一阶段载荷但只要对“找API调用点”这个动作不陌生就很容易切入。甚至游戏修改领域也是同一套逻辑。很多人玩Cheat Engine搜来搜去只能做到“找到某个数值的地址”但你要想知道“是什么代码在改写这个数值”最终还是得回到调试器里下硬件断点、看写入来源。这就是OD和CE配合的经典场景OD找逻辑CE找数据。方法论相通换一个目标训练的底层肌肉是完全一样的那几块。6.2 给新手的几条实在建议第一别把看视频当成练习。每课的内容必须自己亲手操作一遍哪怕全程照抄手指点过一遍的记忆深度和眼睛看过的完全不是一个量级。第二做完一个练习关掉题解、恢复虚拟机快照从头再来一遍。能独立做出来才说明真的会了否则只是“看着会了”。第三每做完一个练习顺手写一段复盘笔记记录自己从运行程序到定位关键代码的完整路径。这个习惯会让你在做到第20课的时候回头看到明显的进步轨迹。还有一条关于心态的建议卡住太正常了。我当年练某个Crackme一个跳转跟了三天才想明白期间一度怀疑自己是不是不适合吃这碗饭。现在回头想卡住的那三天才是真正长进的三天。逆向这个领域没有捷径所有“秒杀”“瞬破”的爽快感背后都是被调试器一遍遍折磨练出来的直觉。这次重做tutorial06OllyDbg的界面还是当年那个老样子视频教程的画质也谈不上好但我最大的体会依然没变逆向真正的门槛不是工具用法而是能不能把“程序行为”和“代码位置”这两张地图无缝拼起来。这个能力一旦成型后续所有高深技巧都只是在上面添砖加瓦。希望这篇复盘能帮你跨过这一道坎。
返回列表