一、存档位置与文件分工
WindowsSteam版默认路径:
C:\Users\用户名\Documents\MyGames\Terraria\Players\→角色档.plr/.plr.bak/配套*.plr.map缩略图
C:\Users\用户名\Documents\MyGames\Terraria\Worlds\→世界档.wld/.wld.bak/*.wld.map
.plr存角色名、外观、HP/MP、背包、装备、饰品、猪猪存钱罐、保险箱、buff、任务进度;.wld存地图尺寸、图格Tile、墙体、液体、NPC、宝箱、事件标记、Boss击杀状态。两者都是自定义二进制序列化+部分加密,不是JSON/XML。
二、加密机制演变(手动解密前必须先判版本)
1.早期1.0~1.1:弱混淆,XNA下Rijndael/AES固定密钥"h3y_gUyZ"(Unicode编码成密钥字节),AES-128-CBC思路雏形。
2.1.2~1.3:正式AES+RijndaelManaged,密钥依旧硬编码在Terraria.exe内,用dnSpy/ILSpy反编译Assembly搜Decrypt/Rijndael/LoadPlayer可定位。
3.1.4.x至今:玩家档.plr主体AES加密块,头部明文存版本号、名字长度、标志位;世界档.wld图格区走压缩(紧凑Tile序列化)+局部加密,宝箱/容器数据嵌在世界流里。
结论:手动改物品不能拿HxD直接硬改密文体,必须先把加密主体解出来成明文二进制流,改完再按同算法封回,否则游戏读档直接报CorruptSave。
三、工具链
•HxD/010Editor:看头、搜明文字符串、按偏移改明文流
-dnSpy/ILSpy:反编译Terraria.exe提取密钥、AES参数、Tile读写顺序
•Python/C#:写解密→改字节→重加密脚本
•TerrariaWikiItemID表+Prefix(修饰语)表:定位物品用
-备用校验:老主机/Xbox版改完要修checksum,PC1.4走AES完整性校验,不重加密必坏
四、.plr手动解密流程(以1.4PC为例)
1.备份:复制Knight.plr→Knight.plr.bak,关游戏再操作。
2.读文件头:前若干字节非密,含magic(0x54524d79之类标识)、version、playerName长度+UTF8名、difficulty(0经典/1中核/2硬核/3旅程)。
3.定位加密块:头部结束后到文件尾为AES密文,长度=文件总长-头部长,必须是16字节整数倍(AES-CBCblocksize)。
4.提取密钥参数(dnSpy搜PlayerFile.StartDecryption):
key=Encoding.Unicode.GetBytes("h3y_gUyZ")截断/补位到16/32字节,IV取自文件头固定字段或全零,模式CBC,填充PKCS7。
5.解密:AES.Decrypt(密文keyIV)→得到明文PlayerBuffer流。此时用HxD打开明文流能看到名字、HP/MP数值、物品段。
6.字节序:PC兴(Little-Endian),Xbox/3DS大端,改多字节数值时注意翻转。
五、物品段结构与手动改物品
解密后的明文流里,物品区布局(1.4主线):
•主背包50格+硬币/弹药8格+装备/饰品/染料/时装/宠物/矿车/钩爪等专用槽
每格Item结构序列化顺序(反向用WikiID对照):
[2字节ItemID][2字节stack(数量)][1字节prefix(修饰语)][1字节favorited/flags]≈6字节起,老版5字节(ID+stack+prefix)
例:把第0格改成“泰拉之刃Zenith(ID757/0x02F5)”,数量999(0x03E7),前缀Legendary(ID82左右,查表):
原:0300010000
改ID兴:F502
改数量兴:E703
改prefix:52(十进制82十六进制)
写回:F502E70352
HP/MP上限字段在名字段后不远处,2字节或4字节兴,直接搜当前数值定位(如满血500→0xF40x01)。
猪猪存钱罐/保险箱/虚空袋:不在主背包连续区,跟随在专属标记段后,结构同Item数组,需按版本偏移表跳。
六、.wld世界档处理差异
.wld不推荐手改图格,体量巨大(小世界几MB、大世界几十MB),结构:
Header(世界名、种子、尺寸、难度、时间、Bossflags)→Tile区(按列压缩序列化,每Tile存类型/墙/液体/线/执行器位标)→Chest数组(宝箱物品用同Item结构)→Sign/NPC/Event区。
手动改宝箱物品:定位Chest区→每箱40槽Item结构→同.plr改法。图格直接改需复刻CompactTileData位域(type占多少位、wall占多少位、液体4位等),不推荐手写,用TEdit类工具更安全。
七、重加密与回填(关键,漏了必Corrupt)
1.改完明文流→AES-Encrypt(明文keyIV)得到新密文。
2.新密文长度若因改大物品名/扩字段变化,需同步修正文件头里的Length字段(若有)。
3.头部原样拼回+新密文→写回Knight.plr。
4.1.4起若引擎带HMAC/校验和,需用同套逻辑重算(多数PC版仅AES-CBC+内部字段自检,无外置checksum;主机版必须修checksum)。
5.进游戏读档验证:角色名正常、物品到位、不报损坏即成功。
八、常见坏档与定位
•打开报CorruptSave:密文没重加密、IV取错、PKCS7填充被破坏、头部长度字段未同步。
-物品变问号/消失:ItemID超出当前版本最大ID、prefix值非法、字节序没翻。
•HP改完回弹:改到缓存副本不是真实字段、或难度模式限制(硬核死亡删档逻辑干扰)。
•世界图格花屏:手改Tile位域错位,必须用TEdit而非HxD动地形。
-Steam云覆盖:改完进游戏前关SteamCloud,否则云快照回写覆盖本地。
九、最小化可行手动改物品脚本思路(C#片段逻辑)
LoadBytes(plr)→切头部/密体→AES128-CBCDecrypt(key="h3y_gUyZ"Unicodeiv)→明文流找inventoryoffset(按名字长度+固定头推算或搜已知物品特征)→写ItemID/stack/prefix→Encrypt回密体→拼头写盘→.bak留存。
Python侧用Cryptodome.AES同参数复刻即可,IV与key长度按dnSpy实际反编译结果校正,不同1.4小版本可能轮换盐值。
整条逆向链路就是:定位路径→备份→反编译取密钥→切头/解密主体→明文流按Item结构改ID/数量/prefix→同算法重加密→拼头回写→关云同步进游戏校验;.wld只动Chest物品,Tile交给专用编辑器,硬碰密文主体必坏档。
WindowsSteam版默认路径:
C:\Users\用户名\Documents\MyGames\Terraria\Players\→角色档.plr/.plr.bak/配套*.plr.map缩略图
C:\Users\用户名\Documents\MyGames\Terraria\Worlds\→世界档.wld/.wld.bak/*.wld.map
.plr存角色名、外观、HP/MP、背包、装备、饰品、猪猪存钱罐、保险箱、buff、任务进度;.wld存地图尺寸、图格Tile、墙体、液体、NPC、宝箱、事件标记、Boss击杀状态。两者都是自定义二进制序列化+部分加密,不是JSON/XML。
二、加密机制演变(手动解密前必须先判版本)
1.早期1.0~1.1:弱混淆,XNA下Rijndael/AES固定密钥"h3y_gUyZ"(Unicode编码成密钥字节),AES-128-CBC思路雏形。
2.1.2~1.3:正式AES+RijndaelManaged,密钥依旧硬编码在Terraria.exe内,用dnSpy/ILSpy反编译Assembly搜Decrypt/Rijndael/LoadPlayer可定位。
3.1.4.x至今:玩家档.plr主体AES加密块,头部明文存版本号、名字长度、标志位;世界档.wld图格区走压缩(紧凑Tile序列化)+局部加密,宝箱/容器数据嵌在世界流里。
结论:手动改物品不能拿HxD直接硬改密文体,必须先把加密主体解出来成明文二进制流,改完再按同算法封回,否则游戏读档直接报CorruptSave。
三、工具链
•HxD/010Editor:看头、搜明文字符串、按偏移改明文流
-dnSpy/ILSpy:反编译Terraria.exe提取密钥、AES参数、Tile读写顺序
•Python/C#:写解密→改字节→重加密脚本
•TerrariaWikiItemID表+Prefix(修饰语)表:定位物品用
-备用校验:老主机/Xbox版改完要修checksum,PC1.4走AES完整性校验,不重加密必坏
四、.plr手动解密流程(以1.4PC为例)
1.备份:复制Knight.plr→Knight.plr.bak,关游戏再操作。
2.读文件头:前若干字节非密,含magic(0x54524d79之类标识)、version、playerName长度+UTF8名、difficulty(0经典/1中核/2硬核/3旅程)。
3.定位加密块:头部结束后到文件尾为AES密文,长度=文件总长-头部长,必须是16字节整数倍(AES-CBCblocksize)。
4.提取密钥参数(dnSpy搜PlayerFile.StartDecryption):
key=Encoding.Unicode.GetBytes("h3y_gUyZ")截断/补位到16/32字节,IV取自文件头固定字段或全零,模式CBC,填充PKCS7。
5.解密:AES.Decrypt(密文keyIV)→得到明文PlayerBuffer流。此时用HxD打开明文流能看到名字、HP/MP数值、物品段。
6.字节序:PC兴(Little-Endian),Xbox/3DS大端,改多字节数值时注意翻转。
五、物品段结构与手动改物品
解密后的明文流里,物品区布局(1.4主线):
•主背包50格+硬币/弹药8格+装备/饰品/染料/时装/宠物/矿车/钩爪等专用槽
每格Item结构序列化顺序(反向用WikiID对照):
[2字节ItemID][2字节stack(数量)][1字节prefix(修饰语)][1字节favorited/flags]≈6字节起,老版5字节(ID+stack+prefix)
例:把第0格改成“泰拉之刃Zenith(ID757/0x02F5)”,数量999(0x03E7),前缀Legendary(ID82左右,查表):
原:0300010000
改ID兴:F502
改数量兴:E703
改prefix:52(十进制82十六进制)
写回:F502E70352
HP/MP上限字段在名字段后不远处,2字节或4字节兴,直接搜当前数值定位(如满血500→0xF40x01)。
猪猪存钱罐/保险箱/虚空袋:不在主背包连续区,跟随在专属标记段后,结构同Item数组,需按版本偏移表跳。
六、.wld世界档处理差异
.wld不推荐手改图格,体量巨大(小世界几MB、大世界几十MB),结构:
Header(世界名、种子、尺寸、难度、时间、Bossflags)→Tile区(按列压缩序列化,每Tile存类型/墙/液体/线/执行器位标)→Chest数组(宝箱物品用同Item结构)→Sign/NPC/Event区。
手动改宝箱物品:定位Chest区→每箱40槽Item结构→同.plr改法。图格直接改需复刻CompactTileData位域(type占多少位、wall占多少位、液体4位等),不推荐手写,用TEdit类工具更安全。
七、重加密与回填(关键,漏了必Corrupt)
1.改完明文流→AES-Encrypt(明文keyIV)得到新密文。
2.新密文长度若因改大物品名/扩字段变化,需同步修正文件头里的Length字段(若有)。
3.头部原样拼回+新密文→写回Knight.plr。
4.1.4起若引擎带HMAC/校验和,需用同套逻辑重算(多数PC版仅AES-CBC+内部字段自检,无外置checksum;主机版必须修checksum)。
5.进游戏读档验证:角色名正常、物品到位、不报损坏即成功。
八、常见坏档与定位
•打开报CorruptSave:密文没重加密、IV取错、PKCS7填充被破坏、头部长度字段未同步。
-物品变问号/消失:ItemID超出当前版本最大ID、prefix值非法、字节序没翻。
•HP改完回弹:改到缓存副本不是真实字段、或难度模式限制(硬核死亡删档逻辑干扰)。
•世界图格花屏:手改Tile位域错位,必须用TEdit而非HxD动地形。
-Steam云覆盖:改完进游戏前关SteamCloud,否则云快照回写覆盖本地。
九、最小化可行手动改物品脚本思路(C#片段逻辑)
LoadBytes(plr)→切头部/密体→AES128-CBCDecrypt(key="h3y_gUyZ"Unicodeiv)→明文流找inventoryoffset(按名字长度+固定头推算或搜已知物品特征)→写ItemID/stack/prefix→Encrypt回密体→拼头写盘→.bak留存。
Python侧用Cryptodome.AES同参数复刻即可,IV与key长度按dnSpy实际反编译结果校正,不同1.4小版本可能轮换盐值。
整条逆向链路就是:定位路径→备份→反编译取密钥→切头/解密主体→明文流按Item结构改ID/数量/prefix→同算法重加密→拼头回写→关云同步进游戏校验;.wld只动Chest物品,Tile交给专用编辑器,硬碰密文主体必坏档。

