- 打卡等级:魔龙套勇士
- 打卡总天数:182
- 打卡月天数:14
- 打卡总奖励:19156
- 最近打卡:2025-10-14 00:17:14
管理员
本站站长
- 积分
- 9039
|
使用特征比对进行逆向工程分析传奇游戏资源包格式,需通过二进制特征提取、结构模式匹配、动态行为验证三大核心技术,系统性定位资源包的格式差异与隐藏逻辑。以下是分阶段实操指南:
一、特征分类与样本收集
1. 核心特征类型
特征维度 典型特征示例 技术价值
文件头魔数 GOM 引擎 PAK 文件头 4 字节为0x50414B00("PAK\0"),GEE 引擎 PAK 前 4 字节为0x47454550("GEE P")。 快速区分引擎类型(如检测到0x57494C00可判定为 WIL 文件)。
索引表结构 GOM 引擎 PAK 索引表条目包含文件名长度(4 字节)、偏移量(4 字节)、大小(4 字节);GEE 引擎索引表新增 CRC 校验字段。 解析资源包内部文件组织逻辑(如确定effect.pak中m34.wav的存储位置)。
加密算法特征 GOM 引擎 PAK 使用固定 XOR 密钥(如chuanqi2),GEE 引擎 PAK 前 16 字节为动态 AES 密钥。 定位解密逻辑入口(如在 IDA Pro 中搜索AES_encrypt函数)。
资源加载顺序 GOM 引擎按 PAK→明文 WIL 顺序加载,GEE 引擎按ResInfo.txt优先级分卷加载。 验证资源覆盖规则(如 PAK 内同名文件是否优先于明文文件)。
2. 样本采集策略
多版本覆盖:收集至少 3 个不同引擎版本的资源包(如韩版传奇 2、GOM 1.80、GEE 3.0),确保特征覆盖全面性。
关联文件配套:同步获取客户端 EXE、登录器、配置文件(如!setup.txt),用于交叉验证特征关联性。
合法来源验证:仅分析已停止运营的版本或个人合法获取的资源包,避免法律风险。
二、二进制特征提取与工具选择
1. 关键工具链
工具类型 推荐工具 核心功能 特征提取场景
十六进制编辑器 HxD、010 Editor 查看文件头、索引表、加密数据区的二进制特征。 提取魔数、文件长度、偏移量等固定字段(如 GOM PAK 的0x04-0x07为总大小)。
反编译器 IDA Pro、Ghidra 分析客户端 EXE/DLL,定位资源加载函数(如LoadPak)。 提取加密算法实现代码(如 GEE 引擎的GenerateDynamicKey函数)。
二进制对比工具 Beyond Compare 批量比对不同版本资源包的二进制差异,高亮新增 / 删除字节。 识别 PAK 文件头扩展字段(如 GEE 引擎 PAK 新增的0x10-0x1F保留字段)。
调试器 x64dbg 动态跟踪资源加载过程,捕获内存中的解密后数据。 验证加密算法正确性(如拦截DecryptPak函数,对比输入输出数据)。
2. 特征提取步骤
文件头特征提取:
用HxD打开 PAK 文件,截取前 32 字节,记录魔数、文件数量、加密标识等字段。例如:
plaintext
GOM PAK头结构:
0x00-0x03: 魔数 "PAK\0"
0x04-0x07: 总大小(小端序,4字节)
0x08-0x0B: 条目数量(小端序,4字节)
对比韩版 WIL 文件头:0x57494C00("WIL\0")后紧跟帧数量(4 字节)、宽度(2 字节)、高度(2 字节)。
索引表模式识别:
使用010 Editor解析索引表,记录条目格式。例如,GEE 引擎 PAK 索引表条目结构为:
plaintext
0x00-0x03: 文件名长度(4字节)
0x04-0x04+n-1: 文件名(UTF-8)
0x04+n-0x04+n+3: 文件偏移(4字节)
0x04+n+4-0x04+n+7: 文件大小(4字节)
0x04+n+8-0x04+n+11: CRC校验值(4字节)
编写 Python 脚本验证索引表完整性:
python
def validate_index(pak_path):
with open(pak_path, 'rb') as f:
f.seek(0x20) # 跳过文件头
entry_count = struct.unpack("<I", f.read(4))[0]
for _ in range(entry_count):
name_len = struct.unpack("<I", f.read(4))[0]
name = f.read(name_len).decode("utf-8")
offset = struct.unpack("<I", f.read(4))[0]
size = struct.unpack("<I", f.read(4))[0]
crc = struct.unpack("<I", f.read(4))[0]
# 验证偏移是否超出数据区范围
data_start = 0x20 + 4 + entry_count * (name_len + 16)
if offset + size > total_size:
print(f"索引表错误: {name} 偏移越界")
加密算法特征捕获:
使用IDA Pro反编译客户端Game.dll,搜索字符串"DecryptFailed"定位加密函数。例如,GOM 引擎的 XOR 解密函数逻辑为:
c
void DecryptPak(BYTE* data, DWORD size) {
for (DWORD i = 0; i < size; i++) {
data[i] ^= 0x66; // 固定密钥0x66
}
}
动态调试验证:用x64dbg在DecryptPak函数入口下断点,运行游戏加载 PAK 文件,观察寄存器值是否与静态分析一致。
三、结构化对比与差异分析
1. 跨版本特征对比表
对比维度 韩版传奇 2 GOM 引擎 GEE 引擎
PAK 魔数 无 PAK,直接存储 WIL/WAV 0x50414B00("PAK\0") 0x47454550("GEE P")
索引表字段 无索引表 文件名长度 + 偏移 + 大小 文件名长度 + 偏移 + 大小 + CRC
加密方式 明文 XOR(密钥固定) AES(动态密钥)
资源加载顺序 按目录顺序加载 PAK 优先,静态密码 分卷加载,MD5 校验
2. 差异定位技巧
二进制差异高亮:
使用Beyond Compare对比 GOM 与 GEE 引擎的Data.pak,观察以下差异点:
GEE PAK 前 16 字节为动态密钥,而 GOM PAK 此处为保留字段(全 0)。
索引表末尾 GEE 新增 CRC 校验字段,导致文件总大小比 GOM 大 4 字节 / 条目。
动态行为验证:
用x64dbg调试 GEE 引擎客户端,在LoadPakWithKey函数处下断点,记录动态密钥生成过程:
plaintext
1. 调用RtlGenRandom生成16字节随机密钥
2. 将密钥写入PAK文件头前16字节
3. 使用AES-256-CBC算法加密数据区
对比静态分析结果,验证动态密钥是否正确应用于解密流程。
资源加载冲突测试:
在 GOM 引擎客户端根目录放置同名 PAK 文件和明文 WIL 文件,观察游戏加载优先级:
若 PAK 内文件被优先加载,则说明 GOM 引擎采用 “PAK 覆盖明文” 策略。
若明文文件被加载,则需检查客户端脚本中LoadResource函数的调用顺序。
四、特征匹配与格式还原
1. 特征匹配算法应用
指纹哈希对比:
对资源包整体或关键字段(如文件头、索引表)计算 SHA-256 哈希,建立特征库。例如:
python
def calculate_fingerprint(file_path, start=0, end=None):
with open(file_path, 'rb') as f:
if end:
data = f.read(end - start)
else:
data = f.read()
return hashlib.sha256(data).hexdigest()
对比不同版本资源包的哈希值,快速识别格式变更点(如 GOM 1.80 与 GOM 2.0 的 PAK 哈希差异)。
模式匹配工具:
使用IDA Pro的Find Cryptographic Primitives插件,自动识别加密函数中的 AES、XOR 等算法特征。
针对自定义加密算法,通过动态调试 + 样本输入输出还原逻辑。例如,V8 引擎的自定义加密可能包含以下步骤:
对数据进行循环左移(ROL eax, 5);
异或固定值0xDEADBEEF;
分段混淆(如前半段与后半段交换)。
2. 格式文档化与工具开发
格式规范编写:
将逆向结果整理为结构化文档,示例(GEE 引擎 PAK 格式):
plaintext
文件头(0x30字节):
- 0x00-0x0F: 动态AES密钥(16字节)
- 0x10-0x1F: 保留字段(全0)
- 0x20-0x23: 魔数 "GEE P"
- 0x24-0x27: 总大小(小端序,4字节)
- 0x28-0x2B: 条目数量(小端序,4字节)
索引表条目(每条目可变长):
- 0x00-0x03: 文件名长度(4字节)
- 0x04-0x04+n-1: 文件名(UTF-8)
- 0x04+n-0x04+n+3: 文件偏移(相对数据区,4字节)
- 0x04+n+4-0x04+n+7: 文件大小(4字节)
- 0x04+n+8-0x04+n+11: CRC校验值(4字节)
解析工具开发:
基于格式规范编写 Python 脚本,验证特征匹配结果:
python
import struct
from Crypto.Cipher import AES
class GEE_PAK_Parser:
def __init__(self, file_path):
self.file_path = file_path
self.key = None
self.header = {}
self.indexes = []
def parse_header(self):
with open(self.file_path, 'rb') as f:
self.key = f.read(16) # 动态密钥
f.seek(0x20) # 跳过保留字段和魔数
self.header["total_size"] = struct.unpack("<I", f.read(4))[0]
self.header["entry_count"] = struct.unpack("<I", f.read(4))[0]
def decrypt_data(self, data):
cipher = AES.new(self.key, AES.MODE_ECB)
return cipher.decrypt(data)
def extract_files(self, output_dir):
# 实现解密与文件提取逻辑...
五、法律合规与风险控制
逆向工程边界:
仅分析已停止运营的版本或个人合法获取的资源包,避免涉及当前商业版本。例如,选择 2003 年韩版传奇 2 客户端进行研究。
不破解商业加密保护或传播解密工具(如 GEE 引擎的动态密钥逆向可能涉及侵权)。
特征库管理:
建立私有特征库时,避免包含未公开的加密算法细节或商业引擎特征。
参考《计算机软件保护条例》第二十三条,确保逆向行为符合 “学习和研究” 目的。
技术规避:
避免逆向反规避技术(如反调试检测模块),仅分析资源包格式本身。例如,跳过对Game.dll中IsDebuggerPresent函数的深入研究。
六、实战案例:GOM 与 GEE 引擎 PAK 特征比对
1. 样本选择
GOM 引擎:Data.pak(版本 1.80,固定 XOR 加密)
GEE 引擎:Res1.pak(版本 3.0,动态 AES 加密)
2. 特征提取与对比
文件头分析:
GOM PAK 头:0x50414B00 + 总大小 + 条目数量
GEE PAK 头:动态密钥(16 字节) + 0x47454550 + 总大小 + 条目数量
索引表差异:
GOM 索引表条目:文件名长度 + 偏移 + 大小
GEE 索引表条目:文件名长度 + 偏移 + 大小 + CRC 校验值
加密验证:
用 GOM 默认密钥chuanqi2解密Data.pak,成功还原 WIL 文件头魔数0x57494C00。
动态调试 GEE 客户端,捕获动态密钥0x1234567890ABCDEF...,解密Res1.pak后数据符合 WAV 文件格式。
3. 工具链协同验证
HxD:对比二进制差异,确认 GEE PAK 前 16 字节为随机密钥。
IDA Pro:分析DecryptPak函数,发现 GOM 使用 XOR 循环,GEE 调用AES_encrypt。
x64dbg:验证 GEE 动态密钥生成流程与静态分析一致。
总结:特征比对流程闭环
plaintext
样本采集 → 二进制特征提取 → 跨版本对比 → 动态调试验证 → 格式文档化 → 工具开发
通过系统化的特征比对,可精准定位不同版本资源包的格式差异,为跨引擎资源移植、私服开发等场景提供技术依据。核心在于静态特征提取与动态行为验证相结合,并始终遵守法律与伦理边界。
|
|