返回
查看原链接原链接
Bilibili1小时3分20秒 · —

洛克王国助手开发手记

基于 CEF + C++ 的《洛克王国》Flash 游戏辅助框架开发复盘

作者基于个人兴趣,为经典 Flash 游戏《洛克王国》开发了一款辅助工具框架:底层采用 C++ 进行内存与数据包处理,上层通过嵌入 CEF(Chromium Embedded Framework)内核提供 JavaScript 开发接口,实现了数据包拦截、修改、转发及前端可视化等完整能力,整个项目以“架构清晰、便于扩展、快速开发”为核心设计目标。

项目背景与动机

为什么做这个项目

  • 作者在吃饭时经常观看直播,无意间刷到《洛克王国》的直播内容,觉得节目效果很好。
  • 《洛克王国》是一款老旧的 Flash 游戏,属于作者的童年回忆(小学初中时期游玩)。
  • 由于近期工作较忙,视频更新暂停,但这个项目已经完成了框架搭建,故以此作为分享内容。

适用范围澄清

重要定位说明(引用原文):*“我录这个视频呢,包括我做这个小助手呢,他呢并不是针对广大的玩家的……因为这个的话呢使用起来的话呢,肯定不是说是像那些现成的网上那些辅助啊。”*

  • 该助手并非面向普通玩家的现成辅助工具。
  • 使用者需要具备一定的开发经验,能够基于框架进行二次开发。
  • 相对于现成的辅助工具(作者评价其大多基于“按键精灵”等老旧的自动化方式),“那种开发的感觉太老太老了,就不是这个时代的产品开发了”。

整体技术架构

架构分层

层次技术选型职责说明
底层C++内存操作、数据包处理、Socket 通信等基础功能支持
中间层CEF(Chromium Embedded Framework)嵌入浏览器内核,提供 JS 执行环境与前后端通信桥梁
上层JavaScript辅助功能逻辑开发,以网页形式呈现 UI 和交互
后端Python Flask(示例)简单数据处理与记录,可自由替换

各层的具体说明

底层选择 C++ 的原因:

  • 进行内存操作时性能更好、更方便。
  • 对上层语言提供支持时,上层无需关注过多底层细节。
  • 作者个人习惯:*“写多了他就习惯了,就习惯用 C++ 了”*——但这并非绝对要求,换成其他语言“其实也无所谓”。
  • 关键原因:需要与 CEF 配合使用。

关于 CEF 选择的重要考量——安全性:

  • 作者最初尝试使用 Windows 自带的浏览器内核(IE 内核),“体验极差,不仅慢,而且非常不安全”。
  • 由于游戏本身依赖 Flash,安全性需要做得更好,因此选择了谷歌开源的 CEF 内核。
  • 上层通过 CEF 提供 JavaScript 开发环境,后端语言可以自由选择(作者使用 Flask 作为简单示例)。

架构的核心设计理念:

  • 整体架构为经典的 B/S(Browser/Server)模式。
  • 底层开发者维护 C++ 侧的 Socket 截持等复杂逻辑,上层使用者*“并不需要去关注这个 C++ 代码是怎么做的,因为这一块是我来维护就完事了”*。
  • 上层开发者只需编写 JS 代码即可实现完整功能,甚至连辅助 UI 都是纯网页(由 VUE 构建)。

Flash 兼容性与浏览器支持问题

Flash 插件支持的现状

  • 从 Firefox 86 版本之后,浏览器已禁止使用 Flash 插件——并非技术上不支持,而是安全策略上的明确禁用。
  • 当前主流浏览器(如 360 浏览器)均已明确显示“不支持该插件”,因为 Flash“太不安全了”。
  • 作者实测发现 Firefox 86 是支持 Flash 的最后一个版本,但即使在这个最后的支持版本中限制也很大。

作者的解决方案

  • 分析阶段:使用 360 浏览器(唯一实测支持 Flash 的现代浏览器),配合“答辩意”(即反编译)软件进行 SWF 分析。
  • 运行时方案:CEF 内核中嵌入指定版本的 Flash 插件(作者携带的是 Flash 30.8 版本)。

Flash 插件的具体运行细节

  • Firefox 76 系列版本可以通过命令行参数设置自动运行 Adobe Flash Player。
  • 但 Firefox 86 即使加上所有命令行参数也无法自动运行 Flash,只能通过右键菜单选择“运行此插件”来手动激活。

SWF 资源分析与逆向过程

SWF 文件获取

  • 作者通过分析游戏中的 XML 配置文件,编写脚本批量下载了大量 SWF 文件。
  • 下载后的 SWF 文件需要专门的工具处理,因为现代浏览器无法直接打开查看。

反编译工具的选择与处理

  • 使用的反编译软件为付费软件,分个人版和企业版。
  • 个人版不支持全部导出功能,使用不便。
  • 企业版功能不够完善——作者通过逆向手段为其增加了一个“全部导出”的功能支持。
  • 导出后就可以像使用 IDEA 一样方便地分析 Flash 的 ActionScript 代码。

加密与解包处理

  • 洛克王国的 SWF 文件存在一层小加密,其中包含一个关键的加密环节,比较复杂。
  • 作者的处理方式类似于做 CTF 逆向:在内存中进行暴力搜索,找到对应的特征码后进行 dump(脱壳)。

ActionScript 代码分析

作者本身并不会 ActionScript 语言,但评价道:*“这个语法极其简单,基本上你不需要去学习,你只要会编程你就能看懂,太简单了。”*

代码结构与评估:

  • 核心逻辑包:以 com 开头的是最重要的包,其中 tenant 下面的 qq Angela 等包为核心处理逻辑,其他包主要负责渲染展示。
  • 对代码质量的评价:*“它的框架搭的非常好,在当时年代来说的话,它已经是一个非常非常赞的框架了”*——属于一种英文的注册机制。
  • 但存在严重问题:*“这个架子中间被各种人给破坏一样,迭代更新,他已经没有原本那种简洁清楚的那种感觉了。”*——游戏年代久远,经过了多代开发人员迭代,代码协调性很差。

数据包格式演变

作者逆向分析了游戏数据包从早期到后期的格式演变,分为几个阶段:

阶段包类型格式特征使用方式
早期plus结构体类型(short 等基本类型拼接)已有框架包(如 input/output 类)
中期Skt(位于 net 包下)结构体风格,继承自 c to s,格式本质不变但风格大变自行解析,不再继承原有基类
后期PB(protobuf)经典的 protobuf 二进制结构需要 protobuf 库解析,也可手动解析但“太不好了”

具体格式说明(早期结构体型):

  • 每个数据包会有一个 A F 头(固定标识),包含结构体头。
  • 头部下面带有 body 部分,每个 body 是实现了 update/input/output 接口的实例。
  • 关键字段包括 flag 和 product ID,根据 flag 进行分发处理。

HTTP 请求类型数据包

  • 游戏后期还出现了 HTB(HTTP)类型的数据包,采用 C++ 命名的请求方式。
  • 带有 CGR 异常等机制,当时年代久远,“很久没有什么特别大的一些革命性改进”。

协议逆向成果与数据规模

协议分析统计

  • 作者对游戏中的协议进行了全面分析:
  • Skt/T 类型的协议约 300 个。
  • PB(protobuf)协议约 300 个。
  • 总计约 600 多个协议全部完成了分析,并提供了给上层的 JS 使用。
  • 实际代码中只写了 300 多个——因为部分 PB 协议“没有名字”,字段名不好命名,就没有放入代码文档。

分析工作量

  • PB 协议的结构需要逐一分析——作者表示“我一个一个分析出来的”。
  • 进行分析的依据:
  • 看到 read from 等方法名,推测与 protobuf 相关。
  • 看到名字像 PB,确认是 protobuf。
  • 根据 protobuf 结构特征进行还原转换。

协议处理的技术细节

protobuf 与 Qt 的兼容性问题:

  • 创建项目时为了防止滥用,作者启用了 MT(多线程)模式。
  • Qt 和 protobuf 同时使用 MT 模式时,在 Debug 版本(第八版本)下 protobuf 支持有问题。
  • 具体表现为:通过反射获取 message 的字符串后,返回的 string 在局部变量中会被立即释放,导致内存错误。
  • 原因推测:type name 应该是引用类型,但实际返回后即释放。
  • 解决方式:测试时去掉 Debug 版本的 protobuf 支持,Release 版本一切正常。

代码规模:

  • 作者展示的一些协议结构体定义文件非常庞大——有 7000~8000 行的。
  • 还有部分协议代码 13,000 多行。
  • 这些工作“并没有任何难度,它只是说非常反锁(繁琐)”。

数据截持与通信机制

截持方式

Socket 层截持:

  • 作者 Hook 了 send 和 receive 函数来实现数据截持。
  • 但游戏实际使用的是 Windows 的异步 Socket 机制(非标准 send),CF 框架虽然完善但存在一个奇怪的 bug。

HTTP/HTTPS 请求处理:

  • 不仅需要截持 Socket 数据包,还需要处理 PB 的请求和回复。
  • 拦截到的请求与数据包会全部转发给上层 JS,由上层自行修改展示或重新发包。

数据发送通道设计

  • 游戏客户端开了两个 Socket 连接:
  • 一个是 login 服务器(登录服务)
  • 一个是 data 服务器(数据传输)
  • 作者通过拦截并转发两个通道的数据实现了完整的通信控制。
  • 发送数据包时需要指定发送到哪个通道(login 还是 data)。

数据包展示与解析

作者实现了对数据包的完整可视化展示:

  • 可以查看每个数据包的 command 类型。
  • 点击“查看详情”可以查看完整的数据内容与解析结果。
  • 对于不同类型的数据(整数、字符串等),提供了转换方法(如 byteToString 方法可将字节数组转为字符串展示)。
  • 示例:房间号 382 在传输中以有符号整数形式出现,显示为负数,实际值应为 331730899——即真正的整数类型。

上层 JS 开发框架功能设计

辅助功能开发模式

作者在底层(C++)中实现了核心逻辑后,上层使用 JavaScript 进行功能开发:

  • 辅助功能全部以 JS 编写,本质上是一个网页。
  • 甚至可以搭建一个 Web 服务,用户只需将网址填入即可动态加载和执行辅助功能。
  • 开发模式为前后端分离:前端(VUE)负责 UI 展示,后端可自由选择(作者用 Flask 做的示例)。

核心 API 设计

消息订阅与回调机制:

// 注册回调示例(伪代码)
// 当数据包请求发过来或收到响应时,回调已注册的函数
// 每个回调接收一个 message 对象
  • 用户可以通过 addCallback 方式注册回调函数。
  • 实现方式:将 JS 函数传递到底层数组中进行保存;当真正回调时,遍历该数组并逐一调用。
  • 回调类型包括:
  • 数据包请求回调(request)
  • 数据包响应回调(reply/receive)

数据包拦截与修改流程示例(瞬移功能):

// 1. 通过 command ID 获取一个对象
// 2. 修改对象中的字段(如房间号 oScene/roomId)
// 3. 通过 getDataByObject 将对象序列化为字节数组
// 4. 通过 sendService 发送字节数组到指定通道(login/data)

具体字段说明:

  • 通过 getObjectCommandId 方法获取对象后,包含 adf 等多个字段,可以通过 console 输出查看。
  • 瞬移相关字段说明:
  • oScene:目标场景/房间号
  • 原始地址字段、零/一标志位等。
  • 回家操作必须将房间号设置为 0(即家园)——因为可能存在好友概念,改房间号也可能去好友家园。

前端页面结构

作者展示了辅助工具的前端截图(未完整美化):

  • 使用 QT 做外壳,UI 使用了 QSS 样式美化。
  • 前端是 VUE 项目编译后由 Flask 直接提供(运行在 localhost:8080)。
  • 配置项通过 YAML 格式管理(引入了 YAML 库)。

页面配置功能包括:

  • command 类型配置
  • 皮肤类型选择(两套,找了免费开源的主题——付费的都是国内厂商出品,作者选择不付费)
  • 是否使用本地路径 + CWD(当前工作目录)
  • 黑夜模式(配置项 tap 设置为 0 开启)
  • 默认请求地址修改

已实现功能模块

功能说明
登录信息展示显示当前登录的 QQ 号、房间号等
瞬移修改场景/房间坐标,实现地图传送
声音控制(关闭)关闭游戏声音
数据包拦截与查看展示所有发出的请求和收到的响应数据包
数据包修改修改数据包内容后转发
获取房间列表请求房间列表并展示(含 IP 地址转换)
虚假房间信息修改返回的房间号(如改为 9999)
修改房间范围将获取房间范围改为 16(获取 16 个房间)
历史数据记录记录登录信息等基础数据

快捷开发能力

作者强调开发脚本非常简单快速:

  • 不需要修改底层 C++ 代码即可完成功能开发。
  • “画完界面,然后 JS 本身就非常非常简单了”。

数据包类型处理详解

Socket 结构体类型数据包

  • 特征:结构体序列化,先有头部标识,再有 body 内容。
  • 开发时对照原版逐个字段定义结构体即可。
  • 代码示例(伪代码):ip 地址从服务端返回为 uint 类型,需要自行转换展示。

Protobuf(PB)类型数据包

  • 特点:有非常明显的 protobuf 结构特征。
  • 解析需要使用 protobuf 库,手动解析不现实。
  • 作者在使用 protobuf 时遇到 Qt+protobuf 在 Debug 模式下的兼容性问题(前面已说明)。

HTTP/XML 配置文件处理

  • 游戏包含大量 XML 配置文件。
  • 这些 XML 是作者批量下载 SWF 文件的途径,也是修改游戏行为的一个切入点。
  • 作者实现了 XML 文件的拦截修改能力:
// 1. 注册一个 AB 的 callback(HTTP 请求回调)
// 2. 在回调函数中获取 content(返回内容)和 maxContentLen(最大可修改长度限制)
// 3. 将 content 替换为修改后的内容(如空字符串或其他自定义内容)
// 4. 修改后页面加载行为会相应改变

HTTP 回调的限制与规避

问题:

  • AB(HTTP)返回包的 callback 中,fill 函数是同步的——因为 V8 引擎的限制(broker 进程和 render 进程不在同一个进程中),异步操作不可行。
  • 只能返回 done(完成)或 cancel(取消)。
  • 为什么需要这类回调:某些返回内容达到 65535 字节上限时无法处理,或者需要更多数据修改时,同步回调无法满足。

作者的解决方案——LoA 库:

  • 自己编写了一个 LoA 库来配合处理子线程的限制。
  • LoA 无法在子线程中做 UI 处理,所以作者又回归 GS 方案。
  • 最终通过 callback 类中的 LoA 函数处理:
  • 传入四个参数:方法(POST/GET)、URL、content(返回内容)、内容长度与最大修改长度限制。
  • 开发者可以在 ContentReplace 相关回调中处理这些内容。

CEF 进程模型与开发者工具

  • 使用 CEF 后,Flash 会开启多个进程(render 进程、broker 进程等)。
  • 开发者可以通过 F12 键打开开发者工具(DevTools)进行页面调试。
  • 作者未默认开启开发者工具——因开启后会比较麻烦,涉及多个进程。
  • 框架默认集成了最新版 Flash(308/30.8),虽然官方已停止维护,但仍有社区开发者在维护。

数据抓取与分析示例

登录过程

  • 游戏启动时会连接本地 QQ 进程的端口(作者在分析时发现 localhost 的端口请求,如 4301),用于获取当前登录的 QQ 信息。
  • 点击登录按钮后,会显示出当前登录的 QQ 号(作者示例中为“奥古斯特”)和登录状态。

房间列表获取与修改

作者演示了一个完整的拦截流程:

1. 发送获取房间列表请求(get room list / get room data)
2. 服务端返回房间列表 reply
3. 拦截 reply,解析返回的房间数据(含 IP 地址、房间号、人数等)
4. 修改数据后转发给游戏客户端
5. 游戏客户端展示修改后的房间列表
  • 每个游戏服务器大约能开十几个端口,每个端口代表一个服务器(登录服务器)。
  • 拦截 reply 的类型包括 room index、room map 等字段。

瞬移功能数据流

// 1. 通过 getObjectCommandId(196612) 获取场景对象
// 2. 修改对象中的位置字段(如:将 oScene 从 382 改为 13,或改为 0 表示回家)
// 3. 通过 getDataByObject 获取字节数组
// 4. 通过 sendService 发送到 data 通道
// 5. 服务端确认后返回响应包(304 类型),游戏完成场景跳转
  • Command ID 196612 对应操作“T4”,含义为切换场景。

项目规模与源码交付情况

资源体积

  • 项目整体体积较大(约 500MB)。
  • 不带 Flash 游戏原版内容(300MB)也有 200MB。
  • 体积大的原因:
  • 携带了完整的 Qt5 库。
  • 携带了 CEF 库及附属文件。
  • 携带了 YAML 库、LoA 库、V8 引擎等。
  • Flash 插件:用户本机无需安装 Flash,直接使用当前路径下的指定 Flash 插件。

项目源码包含

  • 完整的 C++ 底层框架源码。
  • JS 层开发模板与示例(含瞬移、回家、房间列表、数据修改等 DEMO)。
  • 协议分析成果(600+协议的结构体与解析代码)。

适宜开发人群

  • 作者明确说明:适合有开发经验的人进行二次开发。
  • 零基础用户不推荐使用这套框架。
  • 已将“原版”(即原始 Flash 游戏的 SWF 文件)打包,方便开发者对照分析。

开发过程总结与展望

作者对开发难度的评估

  • 数据包分析本身没有技术难点,但极其繁琐。
  • 代码规模巨大主要来自逐一反推结构体定义。
  • 作者表示开发过程是利用每天晚上下班回家后的业余时间完成的,“很干”。

Q&A 与后续计划

  • 作者计划将源码公开发布。
  • 后续内容规划:
  • 回归正轨,继续分享漏洞相关知识。
  • 因近期做了较多 CEF 相关工作,可能分享浏览器漏洞相关内容。
  • 之后还会录制一些溢出(漏洞利用)相关教程。

关键技术术语表

术语说明
CEFChromium Embedded Framework,谷歌开源的浏览器内核嵌入框架
C++底层开发语言,负责内存操作与数据包处理
Flash/SWF游戏使用的老旧多媒体平台,已停止官方维护
ActionScriptFlash 的脚本语言,语法简单,作者评价“会编程就能看懂”
protobuf谷歌的二进制序列化协议,游戏中后期数据包格式
Socket网络通信接口,游戏的两个连接分别用于登录与数据传输
Hook(Hook)拦截系统函数调用的技术,用于数据截持
QTC++ 跨平台 GUI 框架,作者用于构建外壳程序
VUE前端 JS 框架,用于构建辅助功能网页界面
FlaskPython Web 框架,作为后端示例服务
LoA作者自己编写的库,用于处理 V8 引擎限制下的子线程回调问题