《洛克王国》Flash游戏辅助框架的搭建与解析笔记
本项目并非面向普通玩家的现成外挂,而是一套面向开发者的、基于 C++ + CEF + JS 架构的 Flash 游戏辅助开发框架——作者逆向分析了《洛克王国》的 Flash 协议与资源结构,整理出 600 余个网络协议,实现了数据包拦截、修改、转发、ACL 返回内容篡改等核心能力,使开发者可以像写前后端一样用 JS 快速开发各种辅助功能。
项目背景与定位
起因
- 作者(瑞哥)近期因工作繁忙暂停更新视频,但在业余时间做了一个小游戏助手。
- 目标游戏为《洛克王国》(Rock Kingdom),属于 Flash 网页游戏。
- 触发点:作者吃饭时喜欢看直播,无意间刷到洛克王国直播,觉得“节目效果挺好”,且该游戏是童年回忆(小学初中时期),因此产生了做助手的兴趣。
- 游戏现状:非常老旧,且仍为 Flash 游戏。
定位说明
- 并非面向广大普通玩家:作者明确说明这个助手不是给一般玩家使用的现成辅助工具,使用起来不像网上现成的辅助那样傻瓜式。
- 面向开发者:整套框架需要一定的开发经验才能使用;没有开发经验想直接应用的话,建议使用市面成品方案。
- 作者评价成品类的旧方案:大多基于“按键精灵/易语言”等方式在语言层面处理,开发方式“太老太老”,“不是这个时代的产品开发”。
技术选型与整体框架
底层语言:C++
选择 C++ 的原因:
- 内存操作能力强:做助手的基础功能(如内存读取、HOOK 等)需要这一类底层语言的支持。
- 向上层语言隐藏细节:使用 C++ 做底层后,上层语言不需要关注很多操作细节。
- 个人使用习惯:作者写多了习惯了 C++,但也承认“并没有太大特别大的优点”,换其他语言“其实也无所谓”。
- 需求驱动——想用 CEF:作者希望使用 Chromium Embedded Framework(谷歌开源内核),而 Windows 上通过传统 WebBrowser 控件(IE 内核)的方式“极差”“非常不安全”——既然要运行 Flash 游戏,安全性需要做好,因此选择了 CEF。
上层语言:JS
- 通过 CEF 提供上层 JS 语言支持,开发者可以自己编写 JS。
- 上层辅助功能全部用 JS 实现——辅助界面本质上是一个网页。
- 甚至可以搭建 Web 服务,把网址填入框架,即可动态修改和增加功能。
后端:无限制
- 有了 JS 之后,后端语言“无所谓”,可自行选择。
- 作者示例中使用了 Python 相关技术(文中提到 Flask、FastAPI 等),后端仅做了简单示例。
GUI 框架:Qt(QSS 美化)
- 界面基于 Qt 开发,使用 QSS(Qt 样式表)寻找开源主题。
- 作者评价:找到开源主题后整体还算漂亮,其他更漂亮的主题需要付费——经判断是国内开发者的作品,作者选择不付费,“免费开源吧”,自己做了调整。
开发者工具入口
- 在框架界面中按 F12 可打开开发者工具(DevTools),支持查看页面、修改样式、Console 打印等操作。
- F12 开发者工具在 Flash 开启后会涉及不同的子进程类型——如 render(渲染)进程、broker 进程等,整体结构比较复杂,作者默认未开启该功能,原因是防止使用者做不当修改且调试复杂。
Flash 版本兼容性探究
浏览器/CEF 对 Flash 的支持现状
- 现代浏览器几乎均不再支持 Flash 插件。
- 实测 360 浏览器支持 Flash,但作者不愿意下载安装 360 浏览器。
- 作者测试发现:CEF 86 版本是最后一个支持 Flash 的版本;此后版本已明确“不允许使用”Flash(“禁止”而非“不支持”)。
- CEF 86 版本虽支持,但存在很大限制。
- 作者实际使用的 Flash Player 版本为 308(最新版),该版本虽官方不再维护,但作者提到“貌似好像还有自己一些开发者在维护”,可用于一些特殊的高级操作。
- Flash Player 76 开头版本(如 76/77)可以通过右键设置“自动运行 Adobe Flash Player”,但 86 版本无法通过加命令行参数强制自动运行,只能采用右键选择“运行此插件”的方式。
游戏资源提取浏览器
- 作者使用 360 浏览器 加载游戏并进行资源抓取/分析,因为现代普通浏览器已不支持 Flash。
- 抓取手段:搭配一个付费软件(支持抓包/资源导出的逆向工具)对企业版进行了功能增强。
Flash 游戏资源逆向分析
资源下载与整体规模
- 作者将洛克王国的 Flash 资源整体脱取下载下来,数据量很大。
- 脱取时使用了相对高的 CEF 版本(86 版本作为浏览器内核)。
- 随后使用工具对资源进行分析处理。
关键文件加密与破解方法
- 游戏关键资源(SWF 文件)存在一层小加密——在一个非常关键的 A 按键/文件 中存在加密逻辑,复杂度较高,直接拖取文件困难。
- 解决思路借鉴了 DX 逆向(游戏逆向中“内存爆破”类技术):在内存中搜索指定特征码,找到后将其脱出。
- 解锁 Flash 资源的导出能力:原本用于分析的付费软件,个人版不支持导出功能;企业版功能不够完善,作者自行为该软件增加了一个“全部导出”功能支持。
游戏代码框架评估
- 核心逻辑包:以
com开头的最为关键,下面有tenant等子包,再往下是QQ Angela相关包,属于核心处理逻辑;其余属于渲染等用途。 - 编程语言:Flash 使用的 ActionScript(AS 语言)。作者此前不会 AS,但阅读后发现该语言“语法极其简单”,“基本上你不需要去学习”,“只要会 JS 就能看懂”。
- 整体框架质量:在当时年代已经算是非常优秀的框架,采用了类似注册机制的设计。
- 重要发现——框架被破坏:由于游戏运营时间长、经历多代开发人员迭代,原本搭建良好的框架被各种改动所“破坏”,丧失了原本简洁清晰的风格;各代开发人员的更新很不协调。
框架演变:从统一协议到多套并存
游戏数据包协议经历了多代变迁,形成了多套数据包格式并存的局面:
- 早期(正规/简洁时代) :
- 原本是一个正常 Socket + 数据包(ADF 包)结构,有
ADF基类(ADF Base)。 - 数据包结构:一个固定标识(ADF 头)+ 结构体头 + Body 内容。
- Body 中每个实例实现
update/input/output方法(一个输入一个输出);字段包含flag标识、protect ID等。 - 根据
flag作分发处理。 - 编码方式:数据包使用
short等方式进行字段编解码(类似 Flash 自制的序列化/反序列化)。
- 中期(风格分裂) :
- 后续改造后,除了原有
plus包下逻辑外,又新增了Skt包(位于com包下某个net包中)。 Skt系列不再继承原来的类,改而继承CtoS等;包结构变化很大,但“本质上还是一样的”(数据交互本质没变),只是风格改变。- 作者表示这种情况可以接受,“只是框架变了,但数据包交互本质上还是一样”。
- 后期(引入 Protobuf) :
- 出现大量
PB开头的内容——引入了 Protobuf(Google Protocol Buffers)作为新的序列化方案。 - 特征非常明显(典型的 protobuf 结构)。
- Protobuf 数据包需用 protobuf 库解析,手动解析不推荐。
- 作者通过字段名(如
ReadFrom等)初步判断后确认,并将其还原为原本的 protobuf 结构。
- HTTP/ACL 类请求:
- 第三种数据包类型是
ACL/HTB格式——本质上是 C++ 风格的一种 HTTP 类请求(命名方式参考了 C++ CGI 风格),包含大量 XML 文件交互(作者顺带下载了大量 SWF 文件,即通过 XML 清单脚本批量下载的)。 - ACL 请求可返回大量 XML 内容,修改这些返回内容可以实现特殊功能(如替换 XML、清空内容等)。
- 存在 GET/POST 等类型区分,需要处理请求和回复两侧。
协议类型总结
| 协议类型 | 载体/格式 | 出现阶段 | 备注 |
|---|---|---|---|
| 结构体类协议 | ADF 头 + 结构体 + body(T / XT / Skt 等命名) | 早期至中期 | 使用 short 等方式编解码,继承体系因时代不同而变化 |
| PB 协议 | Protobuf | 后期 | 300+ 个协议,需用 protobuf 库解析,可用反射机制处理 |
| ACL/HTB 协议 | HTTP 类请求(C++ 风格命名/XML 内容) | 后期 | 带 GET/POST 参数、需拦截请求与回复、回复可改造 |
协议规模
- 作者共整理协议 600 多个。
- 其中 XT/T 类型约 300 多个,PB 类型约 300 多个。
- 说明:最终展示的列表中仅看到 300 来个是因为部分协议(尤其是 PB 中的)字段没有合适命名而没有写入展示列表,并不代表总量只有这些。
底层功能实现与技术难点
数据包拦截机制
- 为何需要多种拦截:由于数据包类型多达三种(结构体型、PB 型、ACL 型),要实现数据截断、截持和更新,必须分别处理。
- Socket API 拦截的发现历程:
- 作者最初使用 send/receive(
send/receive)方式。 - 切换到 CEF(Chromium 嵌入式框架)后发现:Flash 并没有使用标准
send函数,而是使用 Windows 的异步 I/O(如 `WSASend` 等 Windows 异步 Socket 机制)。 - CEF 框架对异步 I/O 有封装和支持(虽然 CEF 86 是 2018 年左右的产物,但功能比较完善),但存在 bug(会出现一些奇怪的异常问题)。
- 最终实现方式:作者把数据包截取后,包括定位请求在内,全部一股脑转发给上层 JS——由 JS 自行修改、展示或再发包。底层 C++ 代码只需要作者维护即可,上层开发者无需关注 C++ 侧实现。
600 多个协议的手工分析过程
- 协议分析工作量大且极其繁琐。
- 作者每天下班晚上回家就开工,一步步对照,最终“把 800 多个[实为 600 多个]一点点全干出来了”。
- 结构体类协议靠特征识别:先识别 ADF 头,再看返回码/数组数量,逐一编码为 C++ 结构体。
- 代码量极大:某些协议定义文件长七八千行。“没有任何难度,它只是非常反锁 [繁琐]”。
- 辅助工具:
- BASE Struct 文件包含通用结构体类型。
- 真正的特殊结构体(如 T 开头系列)单独定义,内容很长。
Protobuf + Qt 的内存问题(技术坑)
- 项目中使用了 Qt 和 Protobuf 两套依赖,均使用 MT(多线程静态链接)方式。
- 当 Protobuf 升级到第 8 版本时,与 Qt 的 MT 方式兼容性出错(作者不确定是 bug 还是编译特殊指令导致)。
- 现象:使用反射机制处理消息时,返回的
string(type_name返回的字符串)应为带引用的对象,但实际上由于该值产生于局部变量中,返回后立即被释放,导致内存访问错误。 - 处理:测试阶段去掉了第 8 版本的 Protobuf,其他部分一切正常。作者下载了最新版仍存在该问题,未深入分析根因。
Lua 的引入与线程限制
- 作者尝试用 Lua 做所有事(Lua 脚本 + Lua 库),但发现 Lua 无法在子线程中做 UI 处理。
- 结论:Lua 与 JS 各有优劣——这里属于“退了一次,有可能都是退一次”的折衷方案。
辅助框架设计与使用方式
整体架构
架构共分三层:
- 底层(C++ 核心层) :加载游戏、内存操作、数据包拦截与发送、FLASH 支持、hooks、提供 JS 执行环境和数据转换服务。
- 中间桥接层(CEF / V8 / 自定义 API) :向 JS 提供底层接口,注册回调;开发者工具(F12)。
- 上层开发层(JS + 可选任意后端) :辅助界面、业务逻辑、数据展示、数据包拦截与修改等,风格与前后端(B/S 架构)开发一致。
功能面板与配置
- 框架界面加载本地
localhost:8080(由后端服务延伸的端口),后端服务内嵌前端页面(由前端构建产物提供)。 - 配置通过一个 YAML 文件完成(配置量不需要很多),关键配置项包括:
command:自动更改指令;- 皮/主题类型选择(QSS 主题);
- 默认请求地址;
useCWD:是否使用本地路径加上当前路径(作者初期直接用原版 SWF 测试时未使用 Web 服务方式,设 0 时使用本地路径);tap:取值 0 或 1——0 代表黑夜模式(可启用暗色主题)。
消息类型与通道
- 通信分两个通道:
login(登录/校验服务器);data(数据传输)。- 上层发数据包时需在
send时选择相应的通道(如getRoom走login,瞬移等走data)。
核心 API 函数(JS 侧)
作者在 JS 侧通过 V8 扩展为上层提供了一系列封装的函数,大致包括:
- 通过一个
Command ID获取对象(如getObjectByCommandId,内部调用AppView的逻辑——返回带ADF字段的对象,含大量字段可 console 输出查看)。 - 通过对象获取字节数组:
getDataByObject(obj)——对象拼好后转成字节数组用于发送。 send:发送数据包(可选login或data通道)。- 通过
V8函数封装将注册回调函数派发到内部数组,在网络事件到达时遍历回调数组逐一声明调用。 - 回调类型支持
request(请求)与reply(回复)侧拦截;支持拦截后决定丢弃或修改(dc字段标记是否需要修改数据包)。 - 网络数据包经字节流传入后:
- 当类型判定可转换时,使用
ByteToThree/byteToString等方法转为字符串展示。 - 默认展示为“整数类型”字节数组(因部分字段无法判断类型);若开发者确认是字符串,可调用转换方法读取。
- 如
nickname、roomId等字段常用此方式处理。
前端工程介绍
- 前端技术栈:作者使用了 Vue(配合 Vue Router 等),最终将前端编译后嵌入后端。
- 后端技术栈示例:Python Web 框架;(如 FastAPI)负责处理数据、提供接口。
- 实际作者以一个小型演示示例(记录游戏登录、房间信息等功能)作为示例来讲解。
核心功能演示与实现逻辑
数据包日志与查看
- 框架支持抓包:当前端触发游戏内动作(如回家园、瞬移、切图)时,所有经过的数据包(请求和回复)会被截获并展示在日志列表中。
- 每条数据包可点击“查看详情”:
- 显示 Command 类型、请求/回复内容、原始字节、字符串解析值等;
- 如切换房间:客户端发一个 Command(如 304)请求,收到 304 回复;结果显示
mapId=10000(10000 代表家园房间号)、源房间号 382 等。 - 注意:C++/Socket 层传送的目标房间 ID 只能带有符号整数,导致较大正数展示为负数;其真正值是无符号整数形式(如 331730899)。作者在显示上做了“有符号转正”(
UInt→展示为正数)。 - 协议编号对照:如 196612 对应“改变场景”操作(作者通过代码中定义查得)。
功能示例 1:瞬移
具体实现:
- 通过
commandID获取对象(getObjectByCommandId返回 ADF 对象)。 - 修改该对象关键字段,如:
Oses字段为目标场景 ID(如 382);- 原始地址(初始地图等)设为 13(若回家需设置为 0,因为回家请求可能需要区分好友家园:若想去他人家园可填对应好友家园号,
10000是自家家园)。 - 对象构造完成后,调用
getDataByObject(obj)得到字节数组。 - 通过
send发送到data通道。 - 效果:视频演示中角色成功瞬移到目标场景。
功能示例 2:虚假房间列表
- 通过拦截
RoomReply(请求房间范围),获得返回的房间数据。 - 在回调中修改房间号等字段:如将 room index 改成 9999,将 query 返回的房间 ID 改为 999——实现对房间列表的欺骗性修改(展示层面)。
- 根据条件:拦截代码中判断若
command == TDRCommand.reply,并且收到数据包类型为receiveData(收到回复),则将房间号改 999;并设置dc字段为true表示需要修改数据包,否则视为不修改丢弃。 - 可借此实现“虚假房间”“修改房间范围”等扩展功能(如只显示 16 个而不是全部房间),亦可用于快速定位与筛选(例:将房间范围改为 16)。
- 每个房间返回的数据中还包含服务器 IP 地址(以 uint 形式传入),可自行转换展示——每个服务器能开约十几个端口,每个端口代表一个服务器。
功能示例 3:ACL(HTTP 类)请求返回内容篡改
- 演示:拦截一个 ACL 请求的回复,将返回内容(例如 HTML/XML 文本)替换为空字符串或任意字符串。
- 替换为空后页面可迅速加载出来(表现为移除阻塞资源);替换为“123”后页面呈现“123”字样输出——证明改动生效。
- 修改限制:返回内容长度不能超过
maxContent(最大修改长度);若实际需更多空间,框架提供cancel与“需要更多数据”等反馈机制。 - 回调原型(针对 ACL reply 注册的回调函数)传入的参数为五个:
- method(POST/GET);
- URL;
- content(返回内容);
- contentLength;
- maxModifyLength。
- 该功能的意义:可修改游戏加载的 XML 清单字段,实现特殊功能;也可通过此机制批量下载很多 SWF(作者当初就是这样下载游戏资源的)。
- 由于返回包回调是同步回调(同步实现
fil函数):受 V8 引擎限制(进程与渲染线程不同,且开启了沙箱/隔离),同步回调无法异步处理,只能同步返回。无法实现的场景(需要更多数据、出错等)需借用上述参数反馈。 - 调试输出:Qt Debug 输出需要借助文件等方式查看,不太便于直接测试,因此该部分作者没有展开演示。
功能示例 4:注册式消息订阅
- 在 S(上层/脚本初始化)时,先调用所有接口但不对页面做立即修改,而是记录感兴趣的全局字段(如
nickname、uan、roomId)。 - 注册多个回调(提供几个回调接口:请求发过来时回调、收到回复时回调,均传入 message 对象)。
- 可对特定消息注册多个函数,通过数组管理实现“发布-订阅”模式:
- 注册(
addCallback)→ 存数组; - 事件到达 → 遍历数组逐个调用。
- 演示中,对“HighRoom”(改房间)感兴趣时,在回调中修改 room 为 999 并
dc= true,实现拦截修改。
其他细节功能
- 获取/打印每个登录游戏时区服的 IP 地址。
- 好友、会话、防沉迷/时段限制相关逻辑:演示到晚上 11 点后游戏无法登录,连接失败——作者没有深入测试。
- 提供右键运行 Flash Player 插件的适配(当前路径加载 Flash 308 版本)。
开发流程与扩展方式
第三方开发者如何上手
- 底层协议和框架由作者维护;第三方开发者只需要具备前端(JS)能力。
- 辅助功能开发流程 “非常简单”:画界面 + 写 JS,像写前后端一样开发。
- 作者目前以几个简单的示例模板(含注册回调、数据包读取功能、瞬移与虚假房间功能)为开发者演示了 API 用法和工程结构。
- 源码将放出(原版资源一并发布),作者鼓励感兴趣的开发者基于模板做二次开发。但未提供具体发布时间与链接(视频中未提及本期对应的具体仓库地址)。
实现方式对比评述
- 市面已有方案评价:多数基于成熟成品辅助工具研发;但很多是用旧有外挂处理方式,例如在“易语言”这种层级做处理,开发方式落后——与现代前后端开发方式脱节。
- 本框架优缺点评价:
- 优点:开发模式现代、数据包全透明、协议已全部解析、可拦截/修改/代发所有数据包。
- 缺点:体积很大(200~500MB),主要原因是需要完整附带 Qt5 依赖、CEF 库、YAML 库、Lua、Protobuf、Flash 播放器(308 版本)等资源;尤其需要完整带上游戏资源时体积更大(带 Plus/原版资源后约数百 MB)。
目标用户
- 只适合有开发经验、想自己写功能的人;非开发者的普通玩家仍建议使用现成的辅助工具或明确“不是给我这个开发的”。
安全性与限制
Flash 安全背景
- Flash 插件已经被浏览器厂商严格禁止,最主要原因是“太不安全”。
- 网络流传的游戏版本存在较大安全隐患。
- 作者使用 CEF + 独立 Flash 播放器,将运行环境隔离(沙箱/后门模式);提供“后门”来执行 JS 并注入到目标页面(CF 页面)中运行——这类机制存在潜在安全风险,但框架目前局限在作者可控环境中使用。视频中作者强调:“可能需要安全性做得好一点,所有数据处理在我底层完成,上层不需要关心细节”。
框架中尚未完善的部分
- 会话保持(刷新后状态丢失,需重新登录)。
- 服务端校验逻辑(演示用的后端接口未加权限校验;作者预告正式公开应会加上)。
- 界面美化不完整(部分控制面板链接按钮风格与整体不统一)。
- 夜间模式界面还未完整实现。
- Flash 最新版本的完整支持与不稳定 bug 仍未彻底排查(如 CEF 异步 I/O 的怪问题)。
- 体积未优化。
- 未完成所有 YAML 配置项的图形化配置与管理。
- 数据包列表(抓包部分)暂未持久化/未做复杂筛选功能。
后期计划与分享预告
作者后续将“回到正轨”,恢复分享漏洞相关知识:
- 因最近做了较多 CEF 相关工作,可能先讲浏览器漏洞相关内容;
- 还会继续录一些“优异(运维?)/渗透测试”相关的内容,可能会“漏多一点”。
文中未透露具体时间表和已完成进度。
总结
作者从零完成了对《洛克王国》Flash 游戏的数据包协议逆向、资源破解、底层插件化框架搭建和上层开发体系的示例输出,形成了一套结构清晰、便于第三方扩展的辅助开发工具。项目的技术焦点在于:
- C++ 负责所有底层(含 Flash 加载及与 CEF 兼容性适配);
- 上层通过 JS 自由开发,完成所有逻辑和界面;
- 网络层全协议(三种类型、600+ 条)解析完成,做到可拦截、可修改、可转发;
- 因个人精力与时间有限,缺失大量打磨;且因配套资源体积大,不适合轻量分发,其定位偏“开发者自用/二次开发基座”。