尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

逆向工程核心原理笔记(一)——Hello World:用 Ollydbg 断点跟踪 API 调用链

逆向工程核心原理笔记(一)——Hello World:用 Ollydbg 断点跟踪 API 调用链 1. 从 Hello World 开始理解 API 断点跟踪很多人第一次打开 Ollydbg 面对满屏汇编会发懵不知道从哪里下手。其实逆向入门最有效的路径就是拿一个自己写的 Hello World 程序当靶子在 MessageBoxA 这类 API 上下断点观察调用栈和参数是怎么传递的。这篇笔记就围绕这个场景展开把 Ollydbg 的断点配置、寄存器验证、栈回溯这几个动作拆成可以照着做的步骤。你需要的环境很简单一个 Windows 虚拟机或本机、Ollydbg 1.10 或 2.01 版本、一个用 C/C 编译出来的 MessageBox 弹窗小程序。程序本身不重要重要的是你能在调试器里看到它调用 API 的那一刻栈上发生了什么。适合刚接触逆向、想建立“断点—栈—调用链”直觉的读者。下面所有操作都在 Ollydbg 里完成不涉及任何网络工具。2. TaoToken 前置准备让调试环境可复现在开始之前建议先把调试环境固定下来避免每次换机器都要重新配。我习惯用 TaoToken 的模型对话能力来辅助理解汇编片段遇到不认识的指令或调用约定时直接把反汇编贴进去问比翻手册快很多。你可以先到模型对话页面开一个会话后面遇到 MessageBoxA 参数顺序、stdcall 栈平衡这类问题随时查。如果你打算长期做逆向和编码相关的实验Coding Plan 会更合适它把常用的模型调用额度打包在一起适合反复调试和写小工具的场景。接入方式也很直接在 API Keys 页面生成一个 key然后按接入文档里的说明配置到你的脚本或工具里。整个流程不需要额外网络配置就是标准的 HTTP 调用。注意调试器本身不依赖任何在线服务TaoToken 只是辅助你查资料和理解代码不要把它当成调试器的一部分。3. 可复制的 Ollydbg 断点配置步骤3.1 载入程序与预分析把编译好的 Hello World 程序拖进 Ollydbg或者用 File - Open 载入。载入后 OD 会做一次预分析把程序引用的字符串和调用的 API 摘出来。这一步很关键后面找 MessageBoxA 就靠它。如果程序加了壳预分析可能不完整那就需要换用 API 代码断点的方式后面会讲。载入后先按 CtrlG 打开 Go to 窗口输入程序入口点地址确认自己站在 EP 上。然后按 F8 单步走几步感受一下启动函数和主函数的区别。你会发现 main 并不在 EP 位置中间隔着一堆编译器生成的启动代码。3.2 用 All intermodular calls 定位 API 调用在反汇编窗口右键选择 Search for - All intermodular calls。弹出的窗口会列出程序里所有跨模块调用也就是调用的外部 API。按 Name 列排序找到 MessageBoxA 或 MessageBoxW。双击这一行OD 会跳到调用它的那条指令上。这时候你看到的地址就是主函数里调用 MessageBox 的位置。比如常见的CALL DWORD PTR DS:[USER32.MessageBoxW]前面通常有两条 PUSH 指令分别把标题和内容压栈。你可以在这里按 F2 下断点断点会变成红色。3.3 在 API 代码内部下断点如果程序被压缩或保护All intermodular calls 可能列不出东西。这时候换第二种方式按 AltM 打开内存映射窗口找到 USER32.dll 被加载的基址。然后在反汇编窗口右键Search for - Name in all modules在 Name 列里搜 MessageBoxW。双击进入 USER32 里的实现代码在这里按 F2 下断点。这种方式断在 API 内部能更清楚地看到参数是怎么从调用方传到系统库的。缺点是断点位置在系统 DLL 里每次重新载入程序地址可能变需要重新下。3.4 断点管理与注释按 AltB 可以打开断点列表看到所有已设置的断点。双击任意一条就能跳回对应位置。调试时建议用分号;给关键地址加注释比如在调用 MessageBox 的那条 CALL 上写“主函数调用点”。加完注释后右键 Search for - User-defined comment 可以快速找回。标签用冒号:添加适合标记函数入口。比如在主函数第一条指令上打一个:main后面用 Search for - User-defined label 就能直接跳回来。这些习惯在调试大程序时能省很多时间。4. 验证请求与成功结果观察栈和寄存器4.1 断在调用点看参数压栈在CALL MessageBoxW那条指令上按 F2 下断然后 F9 运行。程序会停在 CALL 之前。这时候看右下角的栈窗口ESP 指向的位置往上数四个 DWORD就是 MessageBox 的四个参数hWnd、lpText、lpCaption、uType。因为是 stdcall参数从右往左压栈所以栈顶是第一个参数 hWnd。你可以按 CtrlG 跳到 lpText 指向的地址在数据窗口里看到 “Hello World” 的 Unicode 字符串。这一步能直观验证参数传递的顺序和内容。4.2 断在 API 内部看调用栈如果断在 USER32 的 MessageBoxW 实现里停下来后看栈窗口。ESP 指向返回地址也就是主函数里 CALL 的下一条指令地址。按 CtrlG 输入这个返回地址就能跳回主函数。往上翻几行就能看到完整的调用现场。寄存器窗口里 EAX、ECX、EDX 的值也值得看一眼。stdcall 下 EAX 常用来传返回值MessageBox 返回用户点了哪个按钮。你可以按 F8 单步走过 CALL然后看 EAX 的变化。4.3 用 F4 执行到光标如果不想一步步走可以把光标放在目标指令上按 F4程序会直接运行到那里。配合 CtrlG 定位地址能快速跳过不关心的启动代码。注意 F4 在程序已经运行时不可用必须先暂停。5. 本篇常见错排查断点不生效检查是不是下在了数据段或者没有执行权限的页上。OD 里断点只能下在可执行代码上数据窗口按 F2 是没用的。找不到 MessageBoxA程序可能用的是 MessageBoxW或者被静态链接进了 CRT。用 All intermodular calls 搜 “MessageBox” 关键字两种都看看。栈窗口参数对不上确认调用约定。Win32 API 大多是 stdcall参数从右往左压栈调用方不需要清栈。如果是 cdecl清栈动作在调用方栈窗口看起来会不一样。程序加了壳导致预分析失败这时候 All intermodular calls 可能是空的。改用内存映射 Name in all modules 的方式直接在 USER32 里下断。返回地址跳过去不是主函数可能中间隔了几层封装。沿着返回地址往上翻找最近的函数入口通常就是调用方。6. 继续深入的方向把 MessageBox 这个例子跑通之后你可以试着换一个调用多个 API 的程序比如先 MessageBox 再 CreateFile观察多个断点之间的调用顺序。也可以尝试在 API 返回处下断看返回值怎么影响后续分支。如果你在理解某段反汇编时卡住了把代码贴到模型对话里问一句往往比干瞪眼快。需要批量跑调试脚本或者写自动化分析工具的话Coding Plan 的额度会更够用。API Keys 和接入文档在控制台里都能找到配置一次后面就省事了。
返回列表