
CE 这个东西玩逆向和游戏调试的朋友应该都不陌生。老有人问我为什么放着官方编译好的二进制不用非得自己啃源码答案其实很现实官方发布版经常被各种杀毒软件误报逼着你反复加白名单想跟踪最新特性编译好的 release 总是慢半拍更重要的是既然要拿 CE 做二次开发、做自动化脚本源码在自己手里随时能改心里才踏实。我自己从 7.2 一路编译到现在的 7.5中间踩过的坑可以说是一抓一大把。这篇就把整个编译过程和排查经验完整还原一遍给准备自己动手的朋友当个参考。先说清楚CE 是正经的开源项目源码都在 GitHub 上公开编译它本身就是一道很好的“工程题”。这个过程会逼着你理解 Pascal 工程怎么组织、Lua 怎么内嵌、驱动为什么单独编还会遇到各种工具链版本打架的问题。下面每一步都是实操过的版本号也是我自己验证过能跑通的搭配照着做基本能一次过。1. 编译前先看懂 CE 的工程构成1.1 CE 不是一个项目而是一组项目很多第一次编译 CE 的人会直接栽在第一步从 GitHub 拉完源码打开根目录一看就懵了——里面根本不只有一个工程文件而是按模块拆成了好几个独立项目。CE 从代码构成上看大体可以分成四块第一块是主程序也就是你平时打开看到的那个图形界面。这一部分是用 Pascal 写的编译它需要 Lazarus 加 Free PascalFPC。这也是整个编译工作的主线绝大多数教程教你编译 CE指的就是把这一块编出来。第二块是内核驱动。CE 在 Windows 上读取进程内存时为了绕开系统的防读写机制会加载一个驱动模块。这个部分不是 Pascal而是 C/C 写的编译它需要 Visual Studio 加 Windows Driver KitWDK。如果你只打算用 CE 做用户态的内存分析和脚本调试驱动其实可以不编所以这一块在编译优先级里可以往后放。第三块是 Lua 相关组件。CE 的脚本系统基于 Lua源码里会内嵌 Lua 的解析和执行环境涉及 Lua 头文件和库文件的版本匹配编译时经常在这里出问题。第四块是一堆辅助 DLL 和插件包括处理 Mono/.NET 程序集的模块、处理 UE4 游戏结构的模块等等。这些也会作为独立工程存在在你编译主程序的时候会被一并带上。理解了这四块你就能明白为什么编译 CE 比编一个普通软件要麻烦。它不是打开一个解决方案点一下构建就完事而是要先把几个子模块逐个搞定最后再链接到一起。而且这四块的编译工具链完全不同——Pascal 用 Lazarus驱动用 VS/WDKLua 那块又得保证头文件路径正确。第一次搞光是认清这些模块之间的关系就得花上半小时。1.2 7.2 和 7.5 的编译差异在哪里选版本之前得先把 7.2 和 7.5 的差异讲清楚因为这两版对编译环境的要求有明显区别。7.2 是前几年的大版本它的代码基础还带着一些老工程的痕迹结构相对传统对 Lazarus 版本的要求不高我用 Lazarus 2.0.10 和 2.0.12 都编过都很顺利。编译 7.2 最大的好处是出错概率低适合第一次尝试。7.5 是后来的大版本从界面到内核逻辑都有明显调整。它用的是更新的 Lazarus 特性也引入了更多模块依赖。实测下来7.5 最好用 Lazarus 2.2 以上的版本配 FPC 3.2.2用太老的 Lazarus 会在编译主窗体时报各种找不到类的错误而且报错信息看着跟你的代码有仇似的其实纯粹是编译器不认识新版语法。还有一个区别也得提一嘴7.2 年代网上流传的第三方补丁和辅助脚本非常多如果你打算研究别人改过功能的 CE那主战场基本是 7.2。而 7.5 的源码改动量大社区的衍生版本没那么多但官方源码本身就带了不少新特性。我的建议很简单新手先从 7.2 开始把整套流程走通再去碰 7.5。这样心理落差会小很多。2. 编译环境搭建版本搭配别搞错2.1 为什么要用 Lazarus不用 Delphi先解释一个新手经常问的问题CE 是 Pascal 写的那为什么教程都用 Lazarus而不是直接上 DelphiDelphi 是好东西但它不是免费工具而且 CE 用了一些 Lazarus 特有的控件和组件像 SynEdit 高亮编辑器这类在 Delphi 里还原起来非常费劲。Lazarus 是开源免费环境的代表它的 LCLLazarus Component Library和 Delphi 的 VCL 在 API 上高度兼容CE 官方就是默认用 Lazarus 编译的没必要自找麻烦换 Delphi。Lazarus 本身也是一个大型 IDE安装的时候会自动带上对应版本的 FPC 编译器所以装一个有几百兆的安装包编译器环境就算齐了。2.2 版本对照表照着选就行这里把验证过的版本搭配直接列出来省得你一个个试目标版本Lazarus 版本FPC 版本说明CE 7.22.0.10 / 2.0.123.2.0经典组合稳定报错少CE 7.5 release2.2.23.2.2官方推荐的新工具链CE 7.5 master 分支2.2.6 及以上3.2.2开发版尽量用新版本安装 Lazarus 的时候有一点要注意安装程序会询问是否愿意让它写环境变量、注册文件关联之类的建议全选因为后续命令行编译会用到这些环境。如果你是在 64 位 Windows 上装还要留意安装包本身是 32 位还是 64 位的版本——Lazarus 有 32 位和 64 位两种安装包建议装 64 位的配合编译 64 位 CE 更顺。当然 32 位 Lazarus 也能编 64 位程序只是需要额外配置交叉编译新手别给自己加戏。2.3 除了 Lazarus还要准备什么编译主程序其实只需要 Lazarus 就够了但如果你想把驱动部分一起搞定那还得准备两样东西Visual Studio版本用 2019 或 2022 都行CE 驱动源码写得不算太激进老一点的新一点的都能编Windows Driver KitWDK注意版本要跟你的 Visual Studio 匹配WDK 版本不匹配会导致编译驱动时出现一堆奇怪的宏错误这是老手都会踩的坑。另外源码是用 Git 管理的所以 Git 客户端得装一个。驱动部分在 7.5 里其实还依赖一个子模块拉代码的时候别忘了--recursive参数否则驱动目录会是空的编译到那一步会直接报错说找不到源文件别问我怎么知道的。3. 完整实操从拉源码到跑通进程3.1 拉取源码分支和 tag 的选择既然要自己编译源码肯定是第一步。CE 的官方仓库在 GitHub 上项目名就是 cheat-engine用 Git 直接拉就行。编译 7.5 稳定版的话直接切到对应的 tag 上git clone --recursive https://github.com/cheat-engine/cheat-engine.git cd cheat-engine git checkout 7.5编译 7.2 的话tag 就是 7.2git checkout 7.2这里最关键的隐藏步骤就是--recursive参数。CE 的部分模块以子模块的方式挂在主仓库里不拉子模块的话编译辅助工具和环境检测工具时会报大量文件不存在的错误。我第一次编译的时候偷懒没用这个参数结果折腾了半个多小时才发现问题后来老老实实加上了。顺便提一句如果你之后想跟踪最新功能master 分支上有最新的开发代码。但 master 是面向开发者的有时候官方自己都在改到一半的状态今天的 master 能编过明天可能就不行了所以追求稳定就切 release想追新就做好翻车的心理准备。3.2 用 Lazarus 图形界面编译主程序现在进入正题。在源码目录里找到 CE 主项目的工程文件文件名应该是一个 .lpiLazarus Project Info文件位置大概在源码根目录下的 Cheat Engine 子目录里。双击这个 .lpi 文件Lazarus 会打开整个工程。打开之后先别急着编译先检查一件事目标平台。在菜单栏找到项目 - 项目选项或者直接看工具栏上有没有显示目标系统。CE 默认可能配置成 32 位编译但现在是 64 位系统的天下建议直接设成 x86_64。这一步搞错的话编出来的程序运行时会有一些问题而且你要是想连 64 位目标进程32 位版本根本注入不进去。检查完平台就可以按编译键了。Lazarus 的编译按钮长得很像视频播放器的播放键在工具栏中间区域。点击后下面会出现编译输出窗口一行一行刷信息。第一次编译会比较久因为要把整个 LCL 控件库重新编一遍。正常情况下会经历两个阶段先是 Building LCL然后是 Linking。看到 Linking CheatEngine.exe 这行时基本就快见分晓了。如果编译中途报错不是文件缺失就是控件不认识那大概率就是库没编全或者版本不对。具体报错怎么解后面单独开一章说这里先不岔开。编译完成之后在工程目录的 output 目录下会生成一个 Cheat Engine.exe这就是你的劳动成果。可以直接双击运行如果杀毒软件弹窗拦截先不要害怕这是 CE 的固有属性决定的后面专门说这个问题。3.3 命令行编译更快推荐掌握图形界面编译当然直观但如果你打算反复改代码、反复编译来回在 IDE 里点按钮效率太低。Lazarus 提供命令行工具 lazbuild用它可以在终端里直接编译 CE。进入源码根目录后这种写法可以一步到位编出 64 位版本lazbuild -B --cpux86_64 --oswin64 Cheat Engine/cheatengine.lpi简单解释一下这几个参数-B强制全量编译忽略增量缓存适合在改了版本号、换了工具链之后做一次干净的构建--cpux86_64指定 CPU 架构编 64 位版本--oswin64指定目标操作系统这里是 64 位 Windows。用命令行编译还有个额外好处报错信息抓起来方便直接是纯文本可以复制出来丢给搜索引擎。图形界面下要是报错刷得飞快你想选几行复制都费劲。如果你机器上装了多个 Lazarus 版本建议直接把lazbuild的完整路径写进环境变量否则终端一换就找不到命令。我一般会把C:\lazarus\加进 PATH这样 lazbuild 全局可用。3.4 驱动部分的编译可选主程序编译完之后CE 其实已经可以正常使用大部分功能了。但如果你要在 Windows 上享受完整的读写内存方案尤其是对付某些有保护机制的进程时驱动的地位就很关键。驱动源码在源码根目录下找到驱动子项目里面是 C/C 代码。编译它需要打开开发者命令提示符 for VS或者直接用带 WDK 环境的 PowerShell。进入驱动源码目录后用 MSBuild 编译 x64 版本msbuild CEKext.vcxproj /p:ConfigurationRelease /p:Platformx64编译产物是一个 .sys 文件。但这里有个较大的门槛64 位 Windows 默认只允许加载带有有效数字签名的驱动你自己编译的驱动没有签名系统会拒绝加载。要正式使用得先进入测试签名模式bcdedit /set testsigning on然后重启电脑再加载驱动就没问题了。注意测试签名模式只适合开发调试用不要在生产环境开着它跑。4. 编译报错速查与排查心得4.1 error MSB6006 cmd.exe 已退出代码为 3最经典的 C 项目报错重点说这个错误因为你在搜索引擎里一搜CE 编译 报错这个词条绝对排在最前面。错误原文长这样error MSB6006: cmd.exe exited with code 3.说实话这个报错本身几乎不提供任何有效信息。MSB6006 只是 MSBuild 在运行命令行工具时发现它异常退出这个工具可能是编译器、可能是链接器、可能是资源编译器都有可能。真正的错误原因藏在上一级日志里或者藏在它调用的那个工具自己的输出里。我在编译 CE 驱动的时候遇到过一次当时是 WDK 版本太高跟 VS2019 不匹配导致 rc.exe资源编译器启动失败msbuild 就把锅全甩给了cmd.exe 退出代码 3。排查思路是这样的打开诊断输出。MSBuild 可以打印超详细日志msbuild CEKext.vcxproj /p:ConfigurationRelease /p:Platformx64 /v:diag把输出的最后几百行拖到日志文件里找离 cmd.exe exited 最近的一个error或者fatal字样十有八九能看到真正报错。如果是 rc.exe 挂了检查 WDK 和 VS 版本匹配如果是 cl.exe 挂了检查是不是中间文件目录权限不够或者路径里有中文和空格。另外有个小技巧CE 源码目录建议放在纯英文、没有空格的路径下比如D:\CEBuild。MSBuild 和 Pascal 编译器处理带中文的空格路径时各种怪癖特别多这种约束能少掉一半的疑难杂症。4.2 unit not found找不到 LCL 之类的错误用 Lazarus 编译 CE 时最常见的错误长这样unit not found: LCLBase unit not found: Interfaces看到这种报错先别慌这不是你的代码问题是 Lazarus 环境没配置好。LCL 是 Lazarus 自带的可视化控件库默认应该能直接找到。出现找不到的情况一般有两个原因。第一你打开的 .lpi 工程文件之前是被别的版本 Lazarus 保存过的工程文件里记录的库路径还指向旧版的目录新版自然找不到。解决办法是在 Lazarus 的菜单里找环境选项 - 全局文件路径重新指定 LCL 所在路径或者干脆在工程选项里把使用全局路径打开。第二你装的 Lazarus 是精简版或者绿色版缺少组件包。这种情况建议重装完整版别用绿色版绿色版对编译 CE 这种复杂工程来说就是给自己挖坑。还有一个小细节lazbuild 在编译时如果找不到某个包会直接报package not found: xxx。这个 xxx 可能是 lazcontrols、synedit、lua 这类扩展包。Lazarus 安装包里一般自带这些包但在 IDE 里没有启动它们。可以在组件包窗口里查看每个包是否已经安装把需要的包 Build 一遍再编译 CE。4.3 FPC 版本太老导致的语法报错编译 7.5 的时候有一种很莫名的报错场景代码本身没有任何改动编译时提示某一行unknown identifier或invalid qualifier但你看那行代码明明就是普通的函数调用。这种问题大概率是 FPC 版本太老不支持新版代码里的语法特性。7.5 的代码里用到了一些泛型相关的新特性这些特性老版本 FPC 根本不认识所以会报出一些看似跟实际无关的错误。遇到这种不要在代码里浪费时间先看版本fpc -i如果 FPC 版本低于 3.2.2建议直接升级 Lazarus 套装到 2.2.6 以上FPC 也会随之更新。升级完之后先把工程做一次彻底清理lazbuild 加-B参数可以强制全量重编避免旧目标文件跟新编译器打架。经验之谈编译环境最好是新的比旧的好。有些朋友喜欢用多年以前的绿色版工具链编译老项目也许还行但编 CE 这种活跃开发的项目工具链一定要跟上前进的步伐。4.4 杀毒软件误报这不是编译问题但最烦人编译完 CE双击 exe 的那一瞬间杀毒软件就扑过来了这种经历几乎人人都有。CE 因为本身具备读写其他进程内存的能力特征跟木马有相似之处杀毒软件报警太正常不过。这时候你要做的不是去怀疑自己编译错了而是学会区分真报毒和误报。自己刚编译的源码安全性肯定是可控的源码都在本地代码逻辑你也大致清楚所以这基本上是误报。解决方案无非是把编译产物目录加入杀毒软件白名单或者开发调试时暂时关闭实时防护。还有一点要注意驱动文件 .sys 的误报率比 exe 还要高。因为驱动在系统最底层运行权限级别很高杀软对这种文件极限敏感一旦报毒会直接拦截加载。开发阶段可以把 .sys 生成目录加白名单但等到正式上线分发这一步就牵扯到签名和信任问题了那是另一个话题。4.5 常见报错速查表报错信息出现场景常规解决思路error MSB6006: cmd.exe exited with code 3驱动/VS 编译开诊断日志找内层真正报错检查 WDK/VS 匹配unit not found: LCLBaseLazarus 主程序编译检查工程库路径重装完整版 Lazaruspackage not found: xxxLazarus 主程序编译在组件包窗口安装并编译缺失包Fatal: Cannot find unit SystemLazarus 主程序编译FPC 安装不完整重装 Lazarusunknown identifier7.5 主程序编译FPC 版本过老升级到 3.2.2The system cannot find the file specified插件/辅助工具编译检查 --recursive 拉取的子模块是否存在5. 编译完成后的验证与二次开发衔接5.1 确认版本号别白编译一场编译成功之后第一件事就是验证版本号。打开 CE点击菜单栏的帮助 - 关于如果里面显示的版本号跟你下载的 tag 一致比如 7.5那就说明没有张冠李戴。还有一个容易忽视的验证点检查是不是 64 位版本。在任务管理器里看 CE 进程名称后面有没有显示32 位或者在关于窗口里看目标平台。平时自己玩单机游戏32 位和 64 位都可能能用到但如果你研究的对象是 64 位应用那必须先确认你的 CE 是 64 位版本。32 位 CE 无法正确附加到 64 位目标进程做深度分析这个限制会让后面的操作全部白费。如果编译出来的是 32 位而你需要 64 位回去把 3.3 节里的--cpux86_64参数加上全量重编就行不用改代码。5.2 驱动签名问题和加载失败的检查如果你把驱动也编译出来了加载驱动这一步可能还有坑。加载驱动一般通过 CE 自身的设置界面里面会有驱动安装选项。加载失败时先到事件查看器里看系统日志那里会有驱动加载失败的详细原因。最常见的原因是我上面说的测试签名模式没开加载时提示未经签名或者驱动无法验证签名。其次是版本不匹配——你编译的是 x64 驱动但系统是 x86 的那自然加载不了。检查驱动文件的同时也检查一下系统位数别在这种基础问题上浪费时间。还要提醒一点测试签名模式开启后系统会有一个水印这个是正常现象。测试完成、不需要自编译的驱动之后记得用bcdedit /set testsigning off关闭它恢复系统的默认安全策略。5.3 二次开发的时候把 Lua 脚本环境先跑通很多朋友编译 CE 不只是为了用原版功能而是想做二次开发。CE 的核心能力之一就是 Lua 脚本从自动搜索到修改逻辑都能用 Lua 控制。自己编译的好处就是可以在 Lua 引擎上动手脚加自定义函数甚至替换 Lua 库版本。编译完成后验证 Lua 环境是否正常很简单打开 CE在菜单里找到 Lua 控制台输入一行最简单的测试脚本print(hello from custom build)如果控制台输出了结果说明 Lua 引擎工作正常你的自定义构建已经具备开发条件。之后再加自己的库文件、插件反正整个环境都是自己的怎么蹂躏都行。一些实操后的体会CE 编译这条路走通不难走好却需要一点耐心。我自己第一次编译 7.2 的时候光在环境问题上就耗了一个晚上——Lazarus 版本不对、拉源码忘加递归参数、驱动部分 VS 工程跑不起来。第二遍编译 7.5 就顺手多了整个流程半小时内出 exe驱动也一次通过。所以说这活儿就是第一次折磨人之后越来越简单。如果让我给个最中肯的建议就是别一上来就啃 master 分支。先用 7.2 把整个流程跑顺把环境问题该踩的坑都踩一遍再切 7.5 会比较舒服。编译这个东西工具链版本比什么高超技巧都重要版本匹配了问题就少了一半。再就是遇到报错不要慌先看完整日志再根据日志修改环境比瞎改代码有效十倍。CE 的源码结构清晰编译配置也写得不错它其实是一个很适合拿来练手的大型开源项目。编译完了后面的玩法就多了。