
很多人第一次接触 Cheat Engine都是从“打开游戏 - 扫描数值 - 修改”这条链路开始的。但如果你在逆向、调试或者做游戏模组测试这条路上走得够久迟早有一天会不满足于用别人编译好的二进制而是想把 Cheat Engine 源码拉下来自己从头构建一个“顺手”的 CE。这个念头其实很自然CE 最大的价值不只是那套内存扫描界面而是它整个架构——从注入器、内核驱动到 Lua 脚本引擎全是开源可拆解的。自己编译一遍等于把 CE 从黑盒变成透明的工具箱以后想改界面、加插件、集成自己的自动化分析脚本都不用再求人。这篇文章整理了我在 Windows 环境下编译制作自己的 Cheat Engine 的完整过程覆盖工具链选择、依赖库处理、32/64 位问题、语言包集成以及那一堆让人头大的编译期异常排查。适合有一定编程基础想从源码层面理解 CE、或想深度定制 CE 的读者参考。1. 编译前先想清楚你到底需要一个什么样的 CE1.1 CE 的源码构成与版本选择Cheat Engine 在 GitHub 上有完整仓库地址不赘述。但这里有个关键点CE 的源码构成在不同版本差异巨大。老版本比如 6.x 时代的整个主程序几乎全是 Free Pascal / Lazarus 写的比较纯粹只要装好 Lazarus 就能直接编译。而到了 7.x官方把很多核心逻辑迁移到了 C再用 Pascal 写界面层两者通过动态库方式互相调用。所以你搜“vs2010编译报error msb6006 cmd.exe已退出代码为3”这类报错时会发现大量老教程都在用 Visual Studio 编译 CE 的旧分支那就是 6.x 时代的产物。我的建议是除非你明确要研究老版本架构否则直接从 CE 7.x 的 master 分支开始。原因有三个一是 7.x 的界面和脚本引擎更接近大家日常使用的版本编译出来可以直接替代官方 Release二是社区的新插件、新代码示例基本都基于 7.x三是 Lazarus 配合 FPC 的生态环境比 VS2010 舒服太多VS2010 本身就是个古董级工具在 Win10/Win11 上还经常出莫名其妙的 Windows SDK 兼容问题。1.2 32 位和 64 位之间的微妙关系CE 的编译有个容易让新手懵的地方它不是一个单一 exe 就能搞定的。CE 主程序是 64 位的但它会往被调试进程里注入一个 32 位或 64 位的 kernel 态组件同时还有一个独立的 dbk 内核驱动用于读写受保护内存。具体来说CE 的 Solution 里通常包含这些关键模块Cheat Engine主程序Lazarus 工程编译输出cheatengine-x86_64.exeDBK32/DBK64内核驱动需要 Windows Driver Kit 环境编译默认不强制Trainer creator相关模块用于生成独立修改器一堆 Lua 脚本和语言文件编译后会拷贝到language目录所以你在编译时一般只需要盯住主程序。如果未来要用到驱动级读写再去折腾 DBK 的交叉编译和签名问题。刚开始只需要确保 64 位主程序能跑起来32 位辅助文件能从官方 Release 里拷贝过来用就够了并不影响平时的内存调试工作。1.3 准备工具链Lazarus 与 FPC 的版本搭配CE 官方在 README 里说明用的是 Lazarus FPC但版本要求比较微妙。我用的时候踩过坑FPC 版本太新CE 源码里某些老 API 可能与新版编译器不兼容导致编译期异常版本太旧又可能不支持 CE 代码里用到的新特性。一般来说CE 7.x 的开发环境建议用这两个组合之一组合类型LazarusFPC说明稳定推荐2.2.63.2.2我用下来最稳的搭配基本无编译报错激进新版本3.03.2.3新功能多但部分第三方库可能需要 patch安装时建议选“跨平台”或“Windows 64 位”选项。安装路径千万不要带中文和空格CE 源码对路径空格处理得不好后续编译期经常会冒出一些诡异的找不到文件问题排查起来特别费神。2. 环境搭建与依赖处理2.1 安装 Lazarus 时尽量做减法很多新手装 Lazarus 会选默认全部组件其实大可不必。CE 编译不需要额外的 IDE 组件只需要编译器、LCL 库和基本的 Windows 单元就够了。安装时我通常只勾选FPC、LCL、Online Package Manager其他杂项能省则省。组件越多后续升级和重装越容易版本混乱。装完之后先确认一下fpc是否在命令行可用。打开终端执行fpc -i如果能看到版本信息说明环境正常。如果在编译时提示找不到fpc或ppcx64十有八九是 PATH 没配好。Lazarus 安装目录下的fpc\3.2.2\bin\x86_64-win64需要手动加入系统 PATH这一步别跳过。2.2 QScintillaLua 脚本编辑器的“脸面”CE 的脚本编辑框用的是 QScintilla 的 Pascal 封装这个库是编译过程中最需要耐心的部分。它负责语法高亮、代码折叠、自动补全这些体验。官方源码仓库里一般会引用 QScintilla但不会把库文件直接塞进去而是要求你自己下载对应的 Pascal 绑定源码。我当时踩过最大的坑是QScintilla 的 C 核心库.dll和 Pascal 绑定库.a/.pas版本不匹配。只更新了 Pascal 绑定的源码却忘了换 DLL编译过程不报错一运行程序就闪退。正确的操作思路是去 QScintilla 官方仓库下载对应版本的源码。先编译 C 核心库生成qscintilla.dll。再编译QScintillaPascal绑定生成能被 Lazarus 调用的链接文件。把.dll放到 CE 主程序输出目录把.pas/.ppu放到 Lazarus 库目录。如果你暂时不想折腾 C 那一步也可以直接从官方 Release 里抠一个编译好的qscintilla.dll然后自己只编译 Pascal 绑定层大多数情况下也能跑。但如果你想改脚本编辑器的风格、加自定义语言支持那源码这一层迟早要过一遍。2.3 其他零碎依赖CE 源码里还会用到一些小型单元库比如Lua 5.4绑定时提示找不到Lua库需要单独处理。实际上CE 会把 Lua 官方源码整个塞进自己的组件列表里你不需要额外安装。真正需要你留意的是以下两个WinDivert/TitanHide这类可选安全模块如果不是做反反调试研究可以不用编译。FPCSourceCE 的某些特殊函数需要 FPC 的 runtime 源码参与编译装 Lazarus 时会一并安装但若你安装时取消勾选“Source”目录编译到一半就会报各种 “unit not found” 的异常。依赖这一块我个人的经验是先完整编译一遍遇到什么缺什么再补千万不要提前把所有库都准备得满满当当因为很多库之间有版本依赖关系提前准备反而容易冲突。3. 正式编译流程从源码到 exe3.1 拉源码与目录规划源码拉取这一步没什么好说的git clone下来即可。但目录规划建议动手前就想好我一般放在D:\code\cheat-engine这种全英文且不带空格的路径下。官方仓库分为几个主要子目录Cheat EngineLazarus 主工程文件所在目录里面是.lpi工程文件。library封装好的各种 Windows API 和辅助函数。luaLua 脚本相关源码。bin编译输出目录默认很多中间文件会落到这。如果你想保持源码目录干净可以在 Lazarus 工程选项里调整编译输出目录指向一个单独的output\文件夹。这样后续反复编译时不会污染源码目录。3.2 打开工程并调整编译模式启动 Lazarus 后打开Cheat Engine\CheatEngine.lpi。菜单栏依次进入Project - Project Options重点检查三处编译器路径是否正确Tools - Options - Files - Compiler path。输出目录是否存在且是绝对路径。目标的 CPU 架构默认应该是x86_64如果你的系统是纯 64 位环境这个不用动。编译目标上默认会生成Debug版本。建议第一次编译直接用Release模式因为 Debug 模式会插入大量调试符号编译速度慢一倍生成的 exe 体积也大很多后续运行还容易触发杀毒软件误报。切换到 Release 后在 LCL Widget Type 里选Win32/64这也影响最终界面渲染方式CE 在 Windows 下用原生 Win32 接口最稳。3.3 编译主程序与常见问题预判第一次点击Run或Build时心里要有预期编译过程会比较漫长尤其 LCL 和 Lua 的运行库编译是重头戏。我当时在十几年前的 i7 处理器上跑了大约三到五分钟新机器会快一点。如果一切顺利输出目录下会生成cheatengine-x86_64.exe。此时先别急着双击运行把编译过程里出现的 warning 快速扫一遍确认没有关键库丢失。CE 的编译日志里Fatal级别的报错很少见多数是Warning: ...不影响产物可用。如果日志里看到了Error: unit xxx not found那就要按错误提示逐一补库。常见的是Lazarus的单元路径没有正确添加Project - Project Inspector - Add - Add Unit把缺失单元所在的目录加进去。还有一类编译期异常是路径问题。比如报错FATAL: cannot find unit qscintilla这种除了确认 QScintilla 是否编译正确还要检查 Lazarus 的单元搜索路径是否包含 QScintilla 的.ppu文件所在目录。源码给的示例路径有时是相对路径你把工程挪了位置它就会扑空。3.4 语言包处理中文界面与多语言编译CE 编译完成后默认启动是英文界面。要获得中文界面不需要再重新编译代码只需要把语言文件带出来即可。官方源码里的languages目录保存着各种*.lang文件其中就有简体中文。想省事的话直接从官方 Release 版本里拷贝一份chinese_simplified.lang到你编译产物的languages目录然后在 CE 的Edit - Settings - Language里选择插拔即可。如果想自己改语言包比如修正一些术语翻译、增加自己新增菜单的本地化文本可以一边用 CE 内置的 Language Editor 打开.lang文件一边在界面上对照查看。注意.lang文件本质上是个文本格式的键值对文件用写字板或 Notepad 打开也能手动改但如果涉及到编码尤其是中文最好保持在 UTF-8否则 CE 加载语言包时会乱码。3.5 打包发布里应外合的文件结构编译出来的 exe 不能单独丢给别人用它还需要若干运行时文件。一个最精简的可运行目录应该至少包含cheatengine-x86_64.exe主程序version.dll部分功能会 LoadLibrary 它来获取版本信息dbk32.sys/dbk64.sys内核驱动如果没有则功能受限但普通内存调试没问题languages\目录语言文件Lua\目录CE 内置脚本依赖files\目录部分 Lua 模块和第三方库文件我一般在编译后建立一个干净的dist\目录把这些文件按官方 Release 的目录结构放好再压成 zip。这个 zip 结构和官方分发包很接近以后部署到别的机器上体验和官方版几乎无差。4. 编译中遇到的那些坑与排查4.1 编译报错 MSB6006VS 的“遗毒”怎么破你在搜热词时一定看过“vs2010编译报error msb6006 cmd.exe已退出代码为3”这其实是老教程留给后人的一个常见雷。如果你在用新版 CE 源码理论上不需要 VS2010但如果你出于某些原因还在编译 CE 6.x 项目那很可能会撞上这个错误。这个错误的本质是cmd.exe /c在执行某个命令行工具时失败了回传的退出代码是 3。原始错误信息通常会附在MSB6006之前比如error MSB3075或具体是哪个工具退出的。排查路径有三个方向查看前一行输出。MSBuild 会把具体的命令行打出来手动复制到终端里跑一遍往往能看到真正的报错原因比如路径找不到、权限不足、依赖 SDK 版本不对。检查环境变量。VS2010 时代的编译依赖 INCLUDE、LIB 环境变量如果你装过高版本 VS环境变量可能被覆盖。可以在系统属性里手动补上包括 Windows SDK 头文件和库文件的路径。命令行长度限制。老式工具链经常被超长的 include 路径撑爆把项目挪到短路径比如C:\CE6能立竿见影。如果你并不需要老版本特性我的建议是不要在这上面恋战。CE 7.x 的 Lazarus 路线清爽得多没必要为了一个 6.x 的旧错误耗几个小时。4.2 QScintilla 编译失败的典型场景QScintilla 的编译失败主要集中在这几种缺少make.exe。官方源码通常提供.pro文件用qmake生成 Makefile 后需要make或mingw32-make。如果只装了 Qt 但没装 MinGW就会在这里卡住。Python 版本问题。QScintilla 的生成步骤偶尔会调用 Python 脚本且要求 Python 3.x 的特定小版本不匹配会报语法错误。找不到qscintilla.pro。你在解压源码时如果解压到了中文目录或带空格目录qmake 就会无法定位项目文件。这些错的核心都在于“别追求最新版”。QScintilla 官方有多个稳定分支选一个和你的 Qt 版本匹配的老版本反而最省事。我当时把 Qt 5.15.2 和 QScintilla 2.13.4 配对使用只编译核心库十分钟不到就产出.dll。4.3 编译产出exe打不开闪退怎么办如果编译成功后运行立刻闪退先别慌。排查步骤按顺序来用命令行启动 exe看看会输出什么错误。很多 Windows GUI 程序在有未捕获异常时会往 stderr 打印一段错误信息。确认qscintilla.dll是否在 exe 同目录。如果不在程序会在初始化脚本编辑器的时候崩。确认语言文件是否缺失。如果 CE 找不到默认语言文件它会尝试创建但某些环境写权限不足会导致启动失败。查看 Windows 事件查看器里的Application日志有Exception Code和故障模块名称能快速定位缺哪个 DLL。有一次我编译出的 exe 怎么都闪退最后发现是杀毒软件把dbk64.sys当恶意文件隔离了导致驱动服务启动失败程序连锁崩掉。关掉实时防护重新编译一次问题就没了。4.4 编译慢的根源与优化CE 源码本身不小但编译慢很多时候是环境问题。我做过一个对比实验同样的 i5 主机机械硬盘和 NVMe 固态的差距在编译时间上能拉开一倍。其次Lazarus 默认会用多线程编译但某些第三方库的 Makefile 并不支持多进程这时候必须在 Project Options 里把并行编译关掉否则反而会因资源竞争更慢。还有一个不起眼但很头疼的点杀毒软件。编译 CE 时杀毒软件对生成的.sys文件和 exe 的实时扫描会拖慢大量时间。如果信任自己的源码可以在编译期间临时把输出目录加入白名单。5. 编译之后定制自己的 CE5.1 修改产品名称与版本号编译完成后第一件值得做的事是改版本号。默认 CE 版本号是官方版本号但你自己构建的版本可以打上个人标记。在 Lazarus 工程选项里找到Version Info选项卡把Product Name、File Version改掉顺带在Company Name里写上自己的昵称。重新编译后Windows 文件属性的“详细信息”里就能看到你自己的标识。如果还想改窗口标题栏里的Cheat Engine字样搜索源码里的Application.Title赋值语句改成自己的名字。这种个性化虽然不改变功能但在你自己长期使用时会明显提升工具的“归属感”。5.2 中文语言的深度汉化与修正官方简体中文语言包虽然能用但部分翻译并不符合逆向圈子的习惯。比如某些术语在内存调试语境下直译反而让人困惑。我在使用中会把Opened Process改成“当前进程”把Lock改成“锁定值”把Pointer改成“指针多级偏移”让自己的工具更贴合工作流。用 Language Editor 修改.lang文件时要注意不要重新编译保存后直接切回 CE 主程序按CtrlL重新加载语言文件就能立刻看到效果。这个机制很适合边用边改积累自己的词汇表。5.3 集成自己的脚本和辅助工具CE 的 Lua 脚本接口是它最强大的可扩展点。编译完成后可以在autorun目录里放你自己的.lua脚本CE 启动时会自动执行。比如我写了一个热键切换扫描类型的小脚本编译后的 CE 一启动注册的全局热键就生效省去每次手动点击菜单的麻烦。进一步如果你需要开发自己的外部调试工具CE 社区现在也有很多 MCPModel Context Protocol桥接方案可以让 AI 编程助手直接操作 CE 的内存搜索功能。这类桥接本质就是通过 CE 的 Lua 接口暴露 HTTP 服务编译好的 CE 同样支持加载这些插件因为插件本质就是 Lua 脚本加 DLL 的组合。5.4 交叉编译 Linux 版本的 CECE 在 Linux 下也提供了对应的构建方案。虽然游戏调试主要在 Windows但做服务端内存分析时Linux 版 CE 配合gdb有时很管用。Lazarus 本身支持交叉编译在 Windows 上可以通过lazbuild --oslinux --cpux86_64生成 Linux 可执行文件。不过这一步涉及 Wine 环境模拟配置成本高如果不做 Linux 方面的特定研究暂时不用碰。站在我个人的角度交叉编译更像是“在遇到 Linux 上独特的内存管理问题时才需要的后备手段”平时用不到。你需要更多了解这方面的信息再去单独趟一遍。6. 编译结束后值得保留的几个使用习惯自己编译过一次 CE 之后我最大的感受是官方 Releases 和自编译版之间的差别不只在版本号还在你对这个软件的理解深度。编译过程会逼着你去阅读它如何处理 Windows 进程、如何注入 DLL、如何和内核驱动通信这会反向加深你对内存调试的理解。有个习惯值得坚持每次更新源码之后别急着编译先看一下提交记录和 issues 里别人反馈的问题。CE 的主线版本偶有激进改动等社区热度降下来再更新更稳。另外编译产物要随时备份。我习惯在每次成功编译后把dist目录以日期命名压缩一份比如cheatengine-custom-20250115.7z。这样后续改坏代码或依赖库升级失败时能快速回退到可用状态。最后留个提示自定义编译的 CE 如果涉及内核驱动要注意不同 Windows 版本下的签名策略。普通调试工作完全不需要驱动如果真到了需要处理受保护进程那一步驱动签名和系统版本兼容性又是另一篇长文的容量了。先把主程序编译跑通这套流程走顺已经足够日常使用。