简介plug110是一份面向OllyDBG二次开发的插件源码示例主要服务于逆向工程学习者、漏洞分析人员以及需要扩展调试器功能的开发者。压缩包约209KB共21个文件类型以C/C源码、编译工程、库文件和帮助文档为主.c/.cpp/.h实现插件逻辑与接口声明.mak/.dsp/.dsw/.bpr覆盖多种常见编译环境.lib提供必要的链接库.hlp与.rtf则包含详细开发指南和命令行使用说明整体目录结构清晰适合作为插件开发入门的第一手资料。目前已有229人学习。资源通过书签、命令执行和命令处理等模块示范了如何在调试过程中标记关键位置、调用系统命令并解析自定义命令同时可以从中学习插件的初始化、消息处理、注册与卸载等生命周期环节借助插件头文件可以了解插件接口利用导出函数定义文件掌握OllyDBG核心API的入口而多种编译器工程配置则演示了在不同环境下如何生成可用的插件模块。边阅读源码边对照帮助文档开发者既能夯实插件开发基础也能在具体编译和调试过程中获得可复用的排错思路最终独立构建出符合需求的OllyDBG插件为后续逆向工程工作提供有力支持。 OllyDBG 这个调试器老逆向工程师基本都绕不开。它体积小、启动快、汇编级操作顺手哪怕到了今天处理一些 32 位程序的疑难杂症时我仍然会把它翻出来。而这几年陆陆续续有人问我老版本里那个叫 plug110 的插件包到底包含什么源码还能不能用今天我就结合自己的使用和二次开发经验把 plug110 这套经典插件源码从头到尾捋一遍。内容不只停留在罗列插件清单更会把它的插件机制、编译环境、常见报错以及“怎么改成自己想要的插件”这些实操细节一并说清楚。如果你正打算研究 OllyDBG 插件开发或者只是想把老工具链重新跑起来这篇文章应该能帮你省掉不少弯路。注意文中涉及的所有操作均面向合法的软件调试与逆向分析学习场景请勿用于任何侵权或非法用途。1. 为什么到今天还在看 plug110 这套源码先聊点背景。plug110 诞生于 OllyDBG 1.10 流行的年代那个时期调试器插件生态非常活跃很多后来被广泛使用的调试辅助功能最早都是以插件形式出现的。plug110 并不是某一个插件的名字而是一批围绕 OllyDBG 1.10 开发的插件源码集合。它解决的问题很直接OllyDBG 本身只提供核心调试能力遇到特殊的壳、反调试、资源处理或者内存转储需求时你得自己扩展。那为什么现在还要研究这套源码三个原因。一是学习价值。OllyDBG 的插件接口设计非常干净导出函数就那么几个上手门槛极低。plug110 里的插件代码通常很短每一条消息处理逻辑都对应调试器里的一个真实操作把源码读一遍基本就明白“调试器如何与插件通信”这件事了。这比直接去啃调试器主程序源码要友好得多。二是实用价值。很多经典插件到今天依然能跑而且源码可以按自己的需求修改。比如默认的插件菜单不够顺手你可以改快捷键某个插件对特定壳失效你可以调整检测逻辑重新编译。老插件不代表过时只是缺少维护源码在手就一切好说。三是历史价值。OllyDBG 2.0 之后插件接口有变化很多为 1.10 写的插件已经不再更新。如果你维护的是老工具链或者手里有依赖这些插件的旧工程plug110 几乎是唯一的选择。这套源码适合谁看我的回答是有一定调试器使用经验、想进入插件开发领域的开发者或者做恶意代码分析和软件逆向的老手。纯新手也可以看但最好先熟悉 OllyDBG 的基本操作否则容易在环境搭建阶段就被劝退。2. 插件机制与源码目录先搞懂 OllyDBG 的插件体系2.1 插件接口的核心约定OllyDBG 插件本质上是一个 DLL 文件。主程序启动时会扫描插件目录找到所有符合命名约定的 DLL 并加载。这个约定很简单DLL 必须导出四个关键函数。ODBG_Plugindata ODBG_Plugininit ODBG_Pluginmenu ODBG_Pluginclose分别负责告诉主程序插件名和版本、完成初始化、构建菜单、退出时清理资源。其中 ODBG_Pluginmenu 返回的字符串就是菜单项定义格式类似 0, 插件名称, 功能描述 这样的行文本。这套接口的精妙之处在于主程序通过固定的消息机制和回调地址来调用插件插件不需要关心主程序内部实现。插件和调试器之间的交互通过一条命令链完成OllyDBG 会把自己的关键状态和操作请求以消息形式传给插件窗口。每个插件可以注册自己的窗口类和处理函数这样即使调试器主界面没有变化插件也能主动弹出自己的操作界面。业余开发时你甚至可以完全不用窗口只在菜单里挂功能入口就行。2.2 plug110 的目录结构与常见文件我手头的 plug110 源码包解压后通常会有这样的结构插件源码目录每个插件单独一个目录里面是 .c/.cpp 文件和 .def 定义文件。公共头文件目录OllyDBG 的插件接口头文件例如 plugin.h、ollydbg.h以及一些宏定义。构建脚本以前多用 Visual C 6.0 或 Visual Studio 2005 的工程文件也可能是 Makefile。README 或说明文档有些版本会附带编译和安装说明。这里有个容易忽略的细节OllyDBG 1.10 要求插件文件名符合特定命名规则通常是 xxx.dll 并放在主程序同级的插件目录里。如果 DLL 导出符号不对OllyDBG 启动时会静默跳过不会提示错误。这很容易让人误以为插件没装成功其实问题出在导出签名上。2.3 源码里最常见的消息处理方式plug110 里的插件大多采用注册回调函数的方式工作。比如某个转储插件会在插件菜单里添加一个“转储当前模块”的入口用户点击后触发 ODBG_Pluginmenu 对应的命令码接着插件调用 OllyDBG 的导出 API 读取模块信息和内存数据。举个例子插件里经常出现这样的代码片段cdecl int ODBG_Pluginmenu(int origin, char data[2048], void *item) { if (origin PM_MAIN) { strcat(data, 0, Plug110 示例菜单, 100); } return 0; }这里的 PM_MAIN 表示菜单挂载在主菜单上data 里返回的每一项是“状态码, 菜单名, 命令码”的格式。主程序会根据命令码回调插件的 message 处理函数。理解了这套约定plug110 里的任何插件看起来都不再神秘。3. 源码编译吃透每个环节环境、配置与链路3.1 编译环境的选型编译 plug110 源码最省事的是 Visual C 6.0毕竟它和 OllyDBG 1.10 是同时代产物。但现代机器跑 VC6 比较麻烦我个人的经验是用 Visual Studio 2010 或 2013 打开工程文件手动转换一下即可。理论上 VS2019 也能编但需要修改不少项目配置。具体可以这样操作用 VS 打开 .dsw 或 .vcproj 时它会自动提示升级工程。升级完成后再检查三处设置字符集设置为“使用多字节字符集”因为 OllyDBG 1.10 的接口很多使用 ANSI 字符串。预处理器定义里确认包含 WIN32 和 _WINDOWS。链接器附加依赖库里加入 user32.lib、gdi32.lib 和 kernel32.lib。为什么要强调字符集因为 OllyDBG 1.10 核心是 ANSI 版本插件接口传递的字符串指针默认就是 char*。如果编译成 Unicode菜单定义和函数名处理会出错严重时主程序直接识别不了插件。3.2 mfc42u.lib 加载难题排查这里要专门说说热词里反复出现的“ollydbg加载 mfc42u.lib”。很多人在编译或运行 MFC 类插件时会提示找不到 mfc42u.lib 或 mfc42u.dll。原因在于一些早期插件为了快速开发界面直接动态链接了 MFC 的 Unicode 版本。OllyDBG 1.10 本身不依赖 MFC它内部自己管理界面。插件一旦引入 MFC 动态库系统里没装对应运行库插件就会加载失败。解决办法有两个。如果你只是想运行这类插件请在系统目录里补上 mfc42u.dll 和 msvcp60.dll或者下载对应的 MFC 运行库安装包。如果你要编译源码可以修改工程配置把 MFC 使用方式改为“使用标准 Windows 库”并把源码中依赖 MFC 的部分用 Win32 API 替换。这样做的好处是插件体积更小依赖更少。我自己踩过的坑是编译完的 DLL 在 Win10 上能加载但 Win7 上报“无法定位程序输入点”后来排查发现是我本地链接的是高版本 mfc42u而目标机器上的版本太低。所以建议静态链接或干脆不依赖 MFC。3.3 从源码到 DLL 的完整构建流程下面给出一份适用于现代 VS 的构建步骤按顺序执行基本能编出可用的插件 DLL。第一步打开源码的解决方案文件转换工程格式设置 Release 配置。第二步在“项目属性 - C/C - 常规”里设置“附加包含目录”指向 plugin.h 等公共头文件所在目录。第三步在“链接器 - 常规”里设置“附加库目录”把 OllyDBG 的导出库目录加进来。第四步确认“链接器 - 输入”里包含你需要的外部依赖。第五步编译生成 DLL复制到 OllyDBG 主程序目录下的插件子目录。编译过程中出现“unresolved external symbol”时需要确认是否缺少 .lib 文件以及 .def 文件中是否声明了正确的导出函数。plug110 的源码包通常会附带所有需要的 .def 文件注意不要丢失。提示编译插件时最好使用与目标调试器一致的工具链位数。OllyDBG 1.10 是纯 32 位程序所以插件也必须是 32 位 DLL这个坑很多人第一次编译时会忽略。4. 核心插件逐个拆解功能、用途与集成方式plug110 插件包里包含十几个常用插件这里挑几个有代表性的说。4.1 命令栏插件命令栏插件是最实用的插件之一它给 OllyDBG 增加了一个命令行输入框可以直接输入命令比如 dd、db、dump、bp 等。对于习惯键盘操作的人来说这能大幅提升效率。它背后的实现逻辑并不复杂插件在 OllyDBG 主窗口上创建一个子窗口捕获键盘输入并把命令字符串传给 ODBG_Plugincmd 或者直接调用 OllyDBG 的命令执行接口。源码里最值得研究的部分就是命令解析和转发逻辑你可以照这个思路做出自己的“快捷命令面板”。4.2 内存转储与DUMP插件这类插件用于把调试中的进程内存或模块数据快速保存到文件。OllyDBG 自带“转存”功能但一次性操作比较繁琐。插件可以绑定快捷键一键转储当前执行模块或指定内存区域。源码里会用到 ReadProcessMemory 和 GetModuleInformation 这类 API配合 OllyDBG 导出的模块信息结构体可以拿到模块基址和大小。需要注意转储大内存时不要阻塞调试器界面最好开单独线程来完成写入。4.3 反调试检测插件反调试检测是调试实战中的高频需求。有些程序会通过 IsDebuggerPresent、NtQueryInformationProcess 之类的 API 检测调试状态。plug110 里的隐藏调试器插件通过 hook 这些 API 来伪造“未被调试”的状态。这种插件的源码对新手来说稍难因为它涉及到 inline hook 和异常处理的知识。调试器本身也是一个进程如何把自己的调试痕迹藏起来需要深入理解 Windows 的调试机制。读这套源码时建议配合调试器单步跟踪观察 hook 在内存里改了什么效果非常直观。4.4 附加工具类插件还有一类插件做的是辅助操作比如自动化跳过异常、快速设置断点、记录寄存器快照等。它们的特点是逻辑简单但代码模式很样板化特别适合拿来当插件开发的入门模板。我建议新手从这类插件开始读源码然后逐步往菜单、快捷键、自定义窗口这些功能上扩展。毕竟 OllyDBG 的插件机制并不复杂难的是你想到什么功能并且能把它封装成插件模块。5. 常见问题与排查技巧老插件的那些坑我在使用和编译 plug110 插件时遇到过不少问题现在整理成速查表方便大家直接对照。现象可能原因处理办法OllyDBG 启动时插件菜单为空DLL 未被放到插件目录或导出函数名缺失确认 DLL 放在插件目录用 dumpbin /exports 检查导出编译报错 unresolved external symbol缺 .lib 文件或 .def 未声明导出补全 .lib 引用检查 .def 文件插件菜单出现但点击无反应命令码处理分支缺失或插件版本不匹配在消息处理函数的 switch 里加对应 case运行时崩溃插件与主程序字符集不一致或调用了不安全的 API统一字符集为多字节并用 OllyDBG 提供的封装 APIWin7 上运行提示 mfc42u.dll 缺失插件依赖 MFC 运行库安装运行库或重新编译为无 MFC 依赖版本插件加载后没图标或菜单项乱码ANSI/Unicode 字符串处理不一致检查代码中 strcat/lstrcpy 的使用尤其是最后这个问题实际遇到的人最多。OllyDBG 的菜单字符串缓冲区默认按 char 数组处理如果你用 TCHAR 宏在多字节字符集下没问题一旦切到 Unicode 编译字符串会被截断或编码错误。建议在插件代码里直接使用 char 而不是 TCHAR省掉很多麻烦。插件无法加载时OllyDBG 没有任何错误弹窗这是最让人抓狂的地方。我的排查手段有两个一是用 Dependency Walker 检查 DLL 是否缺少依赖项二是用调试器附加到 OllyDBG 进程在 LoadLibrary 上下断点看加载插件时发生了什么。后者在插件初始化崩溃时特别有效可以看到崩在哪个函数里。6. 拿到源码之后怎么进一步提升改造与实际落地的思路6.1 给老插件加入现代功能很多老插件只有基础的转储、命令功能你可以根据自己的需求改造。比如命令栏插件你可以扩展自定义命令表把常用的脚本序列封装成一条“宏命令”。再比如反调试插件你可以加入对 Process Hollowing、断链隐藏等手法的检测与绕过。具体操作上先保障原有导出函数不动给插件增加一个新的菜单项并实现对应消息处理。这样老功能保留新功能并存不会影响稳定性。6.2 把插件机制迁移到自己的调试工具如果手头有自己的调试器或分析框架OllyDBG 的插件模型完全可以借鉴。它的核心思想是主程序只负责调试原语所有具体策略都由插件承载。你可以按 ODBG_Plugindata、ODBG_Plugininit 的模式设计一套注册接口让外部模块动态加载。这种设计的好处是主程序保持精简功能扩展不需要重新编译主程序。我自己的工具链就是这么做的插件接口沿用 OllyDBG 的思路效果很好。plug110 里的很多源码片段可以直接移植只需把 OllyDBG 的 API 调用替换成你自己的底层接口。6.3 调试器插件开发的通用心法最后分享一点自己的体会。开发调试器插件排在第一位的永远是“稳定性”。插件运行在调试器进程里一旦崩溃就会连累整个调试会话。所以写插件时尽量少用高风险代码所有内存访问都要做有效校验尤其注意 OllyDBG 1.10 没有提供健壮的错误恢复机制。第二点插件功能与调试器功能的边界要清楚。能通过脚本和快捷键完成的事不一定非要写插件。写插件之前先想清楚这个功能是不是高频操作是不是必须有自主界面是不是需要调用系统级 API如果三个答案都是否那就不如直接用 OllyDBG 自带功能。第三点保持源码简洁。Plug110 里的老代码风格偏 C 语言直来直去这其实是个好传统。调试器插件往往是临时工具需要快速迭代与其追求过度设计不如让代码尽量直白方便日后维护。我到现在修改一个老插件还保持着每行代码都尽量短的习惯因为调试器插件调试起来本身就比普通程序麻烦代码简单能省下大量排查时间。plug110 这套源码放在今天看可能界面简陋、功能也不算丰富但它的架构和编码思路仍然值得借鉴。把它读透、改明白你收获的不只是几个能用的插件更是对调试器扩展机制的完整认知。如果你也正在搞相关的东西欢迎分享你踩过的坑和改出来的插件互相交流比闭门造车快得多。本文还有配套的精品资源点击获取