详解《大侠立志传》ES3存档修改:从解密到加密回写全流程 《大侠立志传》的存档一打开就是乱码这是很多想“魔改”玩家卡住的第一道坎。作为一款基于Unity引擎开发的游戏它默认使用了Easy Save 3ES3这套存档方案而ES3在启用加密后会把整个存档内容变成一段无法直接阅读的二进制密文。你就算把.sav文件用记事本强行打开看到的也是“ES3”开头的一大堆无意义字符。这篇文章会把这套ES3存档的完整链路讲透文件结构长什么样、加密逻辑是什么、怎么把存档还原成明文JSON、改哪些字段最实用、改完如何加密回写以及我在实际操作中踩过的各种坑。整个过程不需要你精通编程只要会复制脚本、跟着操作就能跑通特别适合想自己动手改属性、改功法、改物品数量的玩家也适合想研究Unity存档机制的Mod作者收藏。1. 先搞清楚ES3存档的基本盘1.1 大侠立志传为什么不能直接改存档很多从老游戏过来的玩家默认思维是“存档文件就是文本找到数字改掉就行”。但《大侠立志传》这种现代Unity游戏用的存档方案跟老游戏的RPGMaker存档或者明文XML存档完全不是一回事。Easy Save 3是Unity生态里占有率很高的一套序列化插件它把游戏里的对象玩家数据、背包、任务进度、世界状态直接序列化成二进制流再根据配置决定是否加密。大侠立志传在存盘时开启了加密模式所以落盘的存档文件经过了两层处理第一层是序列化把C#对象变成字节数组第二层是加密把字节数组通过对称加密算法变成不可读的密文。这意味着你拿任何文本编辑器去搜索“金币”“等级”“攻击”之类的关键词什么都搜不到。更麻烦的是如果直接拿十六进制编辑器乱改几个字节存档大概率会因为密文被破坏而无法读取。游戏的存档加载流程是“读取文件 - 解密 - 反序列化”这三步任何一步出错游戏就会认为存档损坏。清楚了这一点思路就很直接了想改存档就得把这三步倒着走一遍先解密、再反序列化改完数据后正着走一遍序列化、再加密写回。整个过程核心就是“ES3存档解密修改”这六个字。1.2 ES3的加密链路拆解ES3的加密机制可以理解成一层“保险箱”保险箱本身是文件箱子里的物品是序列化后的数据而开锁钥匙就是游戏的加密密码。ES3支持AES加密这是目前非常常见的对称加密标准密钥长度、加密模式、IV向量这些参数都由插件在初始化时确定。实际落地时ES3存档文件的结构大致分为两段文件头部包含ES3格式标识、版本号、加密头信息这一段是明文用来告诉ES3插件“这个存档是谁写的、用什么版本写的”。数据主体保存着全部游戏状态JSON的密文正常情况下无意义只有持有密钥才能解开。为什么要把头信息暴露出来因为这决定了ES3能不能正确识别文件版本。你修改完数据重新加密时这段头信息要保持原样或者按规则重建不能瞎改。我在一开始折腾的时候就犯过“改了头文件导致游戏完全不认存档”的错后面会详细说。从玩家角度你要搞定的核心问题就两个游戏程序里写死的加密密钥是什么。数据段用了什么加密参数算法、模式、填充方式。这两个信息都在游戏代码里。用dnSpy或ILSpy这类反编译工具打开游戏的Assembly-CSharp.dllUnity游戏主要逻辑程序集搜索“ES3”“Encrypt”“Password”之类的关键词能找到一段设置加密密码的代码。有了密钥之后解密就只是写一段脚本的事。1.3 一眼识别ES3文件的方法有经验的人拿到一个不知道格式的存档第一件事是看文件头。我用HxD十六进制编辑器打开大侠立志传的存档头部几个字节一如既往是“ES3”三个ASCII字符后面跟着版本标识。看到这个开头基本就能断定是Easy Save 3系。辨别是不是ES3还有一个简单粗暴的方法文件体积往往比较大。由于ES3会把整个游戏世界状态都序列化进去大侠立志传这种地图和队友数量很多的游戏存档动不动就是几MB到十几MB跟老游戏几KB的文本存档比起来不在一个量级。另外一个识别点是文件名的后缀。虽然理论上ES3不挑后缀但很多游戏开发者会自己定义个独特的后缀名比如大侠立志传可能用“.sav”“.dat”之类。后缀并不重要认准二进制头才是关键。2. 开工前的准备工具、路径与备份习惯2.1 定位存档文件的三个常用位置Unity游戏存档位置通常有三个套路用户文档目录、本地Low目录、游戏安装目录。大侠立志传这类单机游戏一般会放到“我的文档\My Games\”下以游戏命名的文件夹里但也不排除放到C盘的用户AppData目录下。我自己的查找顺序是这样打开“文档\My Games\”看有没有游戏名或开发商名的文件夹。如果找不到按WinR输入%USERPROFILE%\AppData\LocalLow找开发商或游戏名目录。再不行去游戏安装目录下找“Save”“saves”“Data”这类文件夹。找到存档文件夹后建议你先看一眼有几个存档文件大概什么时候修改过心里有个底。这个文件夹就是之后反复刷新、反复实验的地方。2.2 需要准备的修改工具清单解密修改ES3存档不需要重型设备但下面几样东西是免不了的HxD或其他十六进制编辑器用来查看文件头和验证解密结果不是必须但强烈建议装一个。Python 3环境跑解密脚本和加密回写脚本。没有Python就去官网装装的时候勾选“Add Python to PATH”。pycryptodome库Python的加密库用来做AES解密和加密。装完Python后在命令行执行pip install pycryptodome。dnSpy或ILSpy可选但如果你拿到的游戏密钥不对就得靠它去游戏程序集里找真正的密钥。文本编辑器推荐Notepad或VS Code用来编辑解密后的JSON文件。不要被这么多工具吓到实际流程里你真正深度用到的就是Python和文本编辑器其他都是辅助。2.3 两块不能省的准备工作第一块是备份。这听起来是老生常谈但我真见过不少玩家改完存档发现游戏读不了然后跑来问“怎么恢复”。ES3存档一旦写错游戏会直接判定存档损坏没有后悔药。我的习惯是先把整个存档文件夹原封不动复制一份到桌面或别的盘做好标注“原始备份”每次改之前都重新备份一次当前版本。第二块是关掉云存档。如果开启了Steam云存档或官方云存档游戏启动时可能会从云端拉取旧存档把你刚改好的本地存档覆盖回去。我踩过这个坑辛辛苦苦改了一上午重新进游戏发现角色数据回滚了原因是云同步把旧档拉了下来。所以改存档期间要么在游戏设置里关闭云存档要么在Steam云存档管理里禁用同步。准备工作做完后整个工作流就固定下来了备份存档 - 拷贝一份存档到工作目录 - 解密 - 编辑JSON - 加密回写 - 放回存档目录 - 进游戏验证。3. 核心解密步骤把二进制还原成看得懂的JSON3.1 ES3文件结构与边界定位解密的第一步是先把文件头和数据区分开。这一步非常关键因为ES3文件不是“整个文件一层密文”而是“头部明文主体密文”的结构。如果你直接把整个文件丢进解密函数得到的结果一定是一堆乱码。我这里以最常见的ES3导出格式为例解析流程是读取整个文件到内存。从文件开头开始扫描找头部信息结束的位置。把头部之后的字节作为密文取出来送到AES解密函数。解密后的字节数组用UTF-8解码得到JSON字符串。头部的结束位置怎么判断ES3格式里文件头信息的最后会有一段特定的结束标记。不同版本细节不完全一样但有一个通用的笨办法从第0个字节开始逐字节扫描找到“两个连续的换行符”或“头部声明结束后紧跟加密块的标记”。如果硬编码找不到也可以用固定偏移量。我自己的经验是大侠立志传用的ES3版本头部结束的位置离文件开头并不远几十个字节就能看到边界。你可以用HxD打开存档肉眼观察前面一小段明文部分到哪里截止后面开始出现完全随机的字节那个位置就是“明文头和密文体”的分界线。记录下这个字节偏移量后面脚本直接按这个偏移量切割。3.2 写一个可用的解密脚本含代码下面这个Python脚本是我在实际操作中调整出来的基础版逻辑简单直接你复制保存成es3_decrypt.py就能用import os from Crypto.Cipher import AES from Crypto.Util.Padding import unpad # 需要根据实际情况修改的配置 FILE_PATH rC:\path\to\your\save.sav OUTPUT_PATH rC:\path\to\your\save_decrypted.json HEADER_SIZE 64 # 根据HxD观察到的头文件长度来改 KEY byour-game-encryption-key # 换成在游戏代码里找到的密钥 IV b0000000000000000 # 大部分ES3默认用空IV或者去代码里找 with open(FILE_PATH, rb) as f: encrypted_data f.read()[HEADER_SIZE:] cipher AES.new(KEY, AES.MODE_CBC, ivIV) plaintext unpad(cipher.decrypt(encrypted_data), AES.block_size) with open(OUTPUT_PATH, wb) as f: f.write(plaintext) print(解密完成明文已保存到:, OUTPUT_PATH)脚本里的几个参数需要你根据实际情况替换FILE_PATH拷贝出来的存档文件路径注意是对着副本操作。HEADER_SIZE文件头部长度用HxD数一下明文头占了多少字节。KEY加密密钥字符串需要按字节匹配不够16字节要补足超过16字节要裁切。AES密钥长度必须是16、24或32字节。IV初始化向量最常见的是全零16字节如果你的游戏代码里没特别设置IV就保持全零。这里有同学会问密钥长度不够16字节怎么办ES3处理密钥时通常会做SHA256哈希后截取但不同的游戏可能直接用原始密码的字节数组并做PKCS7填充。最稳妥的方式还是从代码里看它怎么生成Key和IV照搬逻辑。如果实在找不到可以用Python先把字符串转成bytearray再补零到16的倍数试试。3.3 解密成功的判断标准脚本跑完以后如果输出文件大小正常且能打开恭喜你存档已经成功解密。解密完成的明显标志是用文本编辑器打开生成的JSON文件能看到成段的可读内容比如角色名字、等级、经验值、物品ID、任务状态等。大侠立志传的存档解密后通常是一个超大的嵌套JSON里面会有“playerInfo”“inventory”“questData”之类的顶层字段。如果你打开输出文件看到的还是一堆“锟斤拷”或者明显乱码那就说明密钥不对、偏移量不对、或者加密参数不匹配。解密不是一次就能成功的需要来回试几次。我自己的经验是先在HxD里确定头部偏移再去反编译里核对密钥两步都对了基本一次过。4. 改存档的实战属性、金钱与可变数据4.1 解密后的数据长什么样当你第一次成功解密出完整JSON大概率会懵字段实在太多了。别慌你只需要关注跟你修改目标相关的几个部分。以大侠立志传为例常见的数据区块大致可以归成几类玩家角色数据等级、经验、生命、内力、攻击、防御、六维属性体质、灵敏、悟性等通常都在一个叫“player”或“role”或“actor”的对象里。资源数据金钱、门派贡献、声望、制作材料等可能散落在“inventory”“resources”“wallet”这类字段里。物品数据背包物品列表、数量、装备数据通常是一个数组每个元素有物品ID和数量字段。功法/技能数据已学习的武功、等级、经验等一般叫“skills”“kungfu”“abilities”。任务与剧情数据主线任务进度、分支选择、NPC好感度等随处可见“quest”“relation”“favorability”。不建议一口气把整个JSON都搞懂那工作量太大。你需要做的就是先在游戏里看一眼当前角色的某项数值然后去JSON里搜索这个数值。比如游戏里显示金钱是1580那就在解密后的文件里搜“1580”。这个数字绝大部分情况下能直接定位到对应字段非常高效。4.2 修改玩家属性与资源含代码/示例定位到目标字段后修改本身没什么技术含量就是把数字改大、改小或者把物品数量改成你想要的值。但有几个细节需要特别注意第一要区分字段类型。有的字段是数字类型改成字符串会导致反序列化失败有的字段是字符串写成数字也会报错。解密后的JSON里数字不带引号字符串带引号一眼就能分辨。第二物品数量如果是一个独立字段直接改数值通常有效但有些游戏的背包系统数量是按堆叠计算的同一个物品可能存在多行记录你只改一行可能不够。还是老办法在游戏里确认数量搜索到所有出现的位置一起改。第三修改要符合数据逻辑。举例来说大侠立志传的人物属性可能有上限比如单项属性上限是100你改成9999游戏加载时可能会触发非法数据检测直接拒绝读档。改数值不是越大越好我的原则是先改成略高于正常范围的数值进游戏测试如果没问题再继续加。修改完的字段我自己会做一个简单的“改动记录表”在文本编辑器里搜到哪个字段、原值是多少、改成多少全部记下来。这样如果进游戏发现异常能快速定位到是哪一项改出的问题。4.3 动手改之前的三条原则第一条是“一次只改一类数据”。想同时改金钱、等级、物品和好感度听起来很爽但一旦出错你根本不知道是哪个字段写坏了。我的流程是第一轮只改金钱进游戏验证第二轮改属性再验证所有改动都通过后再做一次“最终版”。第二条是“注意JSON的合法性”。JSON对引号、逗号、花括号极其敏感。你哪怕多打了一个逗号游戏加载时JSON解析就会失败存档直接作废。所以修改完以后最好用JSON校验工具检查一下或者用VS Code打开看整个文件有没有红色波浪线报错。第三条是“尊重游戏的数据计算规则”。很多属性不是直接存储的裸值而是带计算公式的。比如攻击力可能等于基础攻击力加装备加成加功法加成你只改存储的“攻击力”字段可能被其他系统覆盖或者被重新计算。遇到这种情况就要去找基础属性、功法等级、装备品质这些“源头字段”改源头才稳定。5. 把改好的数据重新加密写回5.1 加密回写脚本含代码修改完JSON文件剩下的事就是把它重新序列化、加密、并拼回头部生成一个游戏能正常读取的存档。加密回写的Python脚本跟解密脚本是对称的import json from Crypto.Cipher import AES from Crypto.Util.Padding import pad # 配置与解密时保持一致 JSON_PATH rC:\path\to\your\save_decrypted.json OUTPUT_PATH rC:\path\to\your\save_new.sav HEADER_PATH rC:\path\to\your\original_header.bin # 从原存档提取的头部 KEY byour-game-encryption-key IV b0000000000000000 with open(JSON_PATH, rb) as f: plaintext f.read() cipher AES.new(KEY, AES.MODE_CBC, ivIV) encrypted_data cipher.encrypt(pad(plaintext, AES.block_size)) with open(HEADER_PATH, rb) as hf: header hf.read() with open(OUTPUT_PATH, wb) as f: f.write(header encrypted_data) print(加密完成新存档已保存到:, OUTPUT_PATH)回写脚本里有一个容易忽略的步骤你千万不要用解密前读取的整个原文件而是要用“原文件的头部”去拼接“新加密的数据”。原因很简单头部是明文里面记录了文件的格式版本和加密参数这些信息在修改过程中不能动。所以我在解密之前会先单独把原文件的头部字节保存成一个bin文件供加密回写时使用。如果你一开始没保存头部可以从原始备份的存档文件里重新读取前HEADER_SIZE个字节效果一样。5.2 回写后的验证流程新存档生成之后先别急着替换原存档一定要先在游戏外用工具验证一次。验证分几步用HxD打开新存档确认头部前几个字节跟原存档完全一致后面数据区的字节顺序跟原存档不同因为内容改了。试着用解密脚本再解一次新存档看能不能解出一个跟你修改后JSON完全一样的明文。确认无误后把新存档复制到存档目录替换或改名成游戏能识别的文件名。第一次替换建议走“保守路线”把原存档改名成save_backup.sav把新存档命名成save.sav。这样万一新档有问题马上能把旧档改回来不用重新解包备份文件夹。替换完以后进游戏看主菜单能否正常显示存档信息能否正常进入游戏、查看角色面板。如果一切正常恭喜存档修改大成功。6. 常见报错与排查实录6.1 解密乱码的几种原因问题现象最常见原因解决办法解密输出跟原文件差不多长但全是乱码密钥错误或密钥编码方式不对用dnSpy去游戏程序集里核对密钥字符串注意字符串用UTF-8还是ASCII循环左补或右补到16字节解密输出只有一小段可读后面全乱数据偏移量不对切割位置偏了重新用HxD核对头部边界多试几个偏移量报错“Input data must be a multiple of the block size”解密前没有按块大小对齐确认你取出的密文长度是16的倍数如果不是说明切割位置错了报错“Padding is incorrect”IV不对或密钥不对检查IV是否为全零密钥是否做了额外变换如哈希取前16位第一个乱码问题最常见原因是游戏代码里设置的加密密码不是平铺的字符串而是先做了某种变换。ES3的AES加密密码默认会用SHA256做哈希取前32字节作为256位密钥。如果我在脚本里直接用原始密码的16字节解密出来的就是乱码。这种情况下你需要先对密码做hashlib.sha256计算再把digest传给AES。6.2 回写后游戏无法读档的排查游戏不认新存档九成原因是文件头被破坏了或者JSON不合法。我记得很清楚第一次回写时偷懒直接用“整个原文件”跟“新加密数据”做了拼接忘了头文件里其实还藏了文件长度和校验信息。结果游戏读完档直接弹“存档损坏”。后来老老实实只切头部、只拼数据问题就消失了。还有一个容易忽略的点加密后的数据长度可能跟原数据长度不一致。如果你修改的字段变长比如把物品名称改成更长的字符串加密块大小也会变化。游戏加载时如果对文件长度有固定校验就会拒绝读取。碰到这种情况你得在JSON里保持数据规模跟原版接近不要新增或删除大段结构只改数值是最稳妥的。6.3 数值改了但游戏里没变化的坑你解密、修改、加密、回写全都成功了进游戏却发现数值纹丝不动这种挫败感我太懂了。这个问题的根源通常是“改错地方”。游戏数据可能存在多份一份是角色面板显示的“派生属性”一份是底层的“基础属性”。金币也可能在多个地方有记录比如背包里有一份“钱包数值”任务系统里有一份“累计获得”你只改了前者后者读档时把前者覆盖了。解决办法是先确认字段唯一性。在JSON文件里搜索你要改的数值如果搜出来好几个地方都有全部改成目标值再加密回写。如果只有一个地方那基本就是正确字段。另外有一种特殊情况有些游戏读档后会触发“自动校验修复”发现数据异常直接悄悄改成合理值。这种就没办法靠改存档解决只能先改一个小幅度数值试水看游戏是否容忍。6.4 我的存档修改工作流最终定稿做了这么多最后把我现在的完整工作流整理给大家照着做基本不会再翻车关闭Steam云存档打开存档目录完整备份整个文件夹到桌面。复制一份存档到工作目录用HxD确认文件头部和数据区边界计算出HEADER_SIZE并把头部单独保存成header.bin。用dnSpy确认游戏加密密钥跑解密脚本得到明文JSON。在JSON里搜索游戏里对应的数值定位目标字段一次只改一类数据改完用VS Code检查JSON合法性。跑加密回写脚本生成新存档用解密脚本反向验证一遍。把新存档复制进存档目录把旧存档改名留底。进游戏验证如果失败删掉新存档把旧存档改回来。这套流程我前前后后改了几十次存档除了第一次因为头文件拼接踩了坑后面基本每次都能一次成功。真正关键的节点其实就三个头部边界能不能找对、密钥能不能拿对、JSON改完合不合法。三个节点都控制住ES3存档解密修改就不存在什么玄学问题。最后分享一个小技巧解密后的JSON文件建议保留一份不用重复解密。以后想再改直接对明文JSON动手重新加密一次就行。省去每次解密的步骤还能顺便练手做一套自己专用的人物模板比如“开局满资质模板”“锁定功法模板”以后新开周目直接套用能省掉大量重复坐牢时间。