逃跑吧少年拆包乱码问题的解决

问题内容

遇到问题

6月3日逃跑吧少年PC端游戏更新。让我康康逃跑吧少年拆包乱码问题的解决
咦~别的类型的文件还好,怎么TextAsset文本文件只有一个字母?难道是我的AssetStudio坏了?先Export出来康康。
逃跑吧少年拆包乱码问题的解决
好家伙乱码了。要是前几个版本,数据一般是保存为csv格式的文本文件。难道白日梦为了不让玩家拆包查看更新逃跑吧少年拆包乱码问题的解决
出现正常文字了,编码选择没错。但是可读字符串之间还混进不少不可读的二进制数据,看来应该是将数据序列化后保存的结果。
文件中似乎不存在变量名、类型等信息,应该不会像php那样不需要构造数据类型就能直接反序列化。还是逆向分析一下吧。

简单分析

本人逆向还未入门,不过只是获取反序列化所需的对象定义和序列化的方法应该就能完成反序列化,还是硬着头皮上吧。
Il2CppDumper,启动!DnSpy,启动!
先直接搜索文件名试试:
逃跑吧少年拆包乱码问题的解决
这个ZeroFormatter命名空间有点可疑,点开看看。
逃跑吧少年拆包乱码问题的解决
Aha,重写了Serialize和Deserialize方法,看来这个ZeroFormatter应该就是序列化器了。搜了一下,这似乎是C#中最快的序列化器,看来这次游戏改格式更多是出于性能的考虑吧。
![ ](https://img-blog.逃跑吧少年拆包乱码问题的解决
逃跑吧少年拆包乱码问题的解决
进而猜测ActivityLobby文件中存储的就是这个类的实例序列化的内容。接下来的任务就是对数据进行反序列化了。

解决问题

反序列化

因为我比较菜游戏会校验文件hash值,修改或者注入会比较麻烦,所以我选择写一个简单的反序列化程序,负责读取序列化后的数据并转换为可读的数据。
VS2019,启动!创建一个.Net控制台应用,通过NuGet安装ZeroFormatter和ZeroFormatter.Interfaces。
逃跑吧少年拆包乱码问题的解决
ZeroFormatter的基本使用不难,序列化的方法很简单,就是创建类、创建实例对象、序列化对象三步。进行序列化类的定义官网也给出了明确的规定,主要就是类需要指定ZeroFormattable,属性需要指定Index并且要加上virtual关键字。
先根据ActivityLobbyInfoObjectSegment直接创建一个ActivityLobbyInfo类:

[ZeroFormattable] public class ActivityLobbyInfo { 	[Index(0)] 	public virtual int Id { get; set; }  	[Index(1)] 	public virtual string TabName { get; set; }  	[Index(2)] 	public virtual ActivityType Type { get; set; }  	[Index(3)] 	public virtual string Prefab { get; set; }  	[Index(4)] 	public virtual string TitleName { get; set; }  	[Index(5)] 	public virtual int Rank { get; set; }  	[Index(6)] 	public virtual string Desc { get; set; }  	[Index(7)] 	public virtual ActivityCollectionType CollectionType { get; set; }  	[Index(8)] 	public virtual int[] PreviewActivityIDs { get; set; }  	[Index(9)] 	public virtual string TimeDesc { get; set; }  	[Index(10)] 	public virtual int version { get; set; }  	[Index(11)] 	public virtual int gradeLimit { get; set; }  	[Index(12)] 	public virtual int Index { get; set; }  	[Index(13)] 	public virtual int startTime { get; set; }  	[Index(14)] 	public virtual int endTime { get; set; }  	[Index(15)] 	public virtual int exchangeEndTime { get; set; }  	[Index(16)] 	public virtual int MobileTimeOffset { get; set; } } 

其中部分枚举类型的数据也要根据逆向的结果进行定义:

public enum ActivityType { 	PREVIEW, 	COLLECT_WORD, 	DAILY_COLLECT_WORD, 	MICRO_PAYMENT, 	CUMULATION_RECHARGE, 	WHEEL, 	LOGIN_ACTIVITY, 	BUY_NEW_CARD_DIRECT, 	NEW_CARD_UPGRADE_REWARD, 	NEW_CARD_GIFT, 	FIRST_RECHARGE, 	CHARACTER_PREVIEW, 	CHARACTER_BUY_DIRECT, 	CHARACTER_TASK_ACTIVITY, 	CHARACTER_GIFT, 	SHARE_ACTIVITY, 	COMMON_TASK, 	COMMON_EXCHANGE, 	CHARACTER_LOTTERY, 	ANNIVERSARY_GIFT, 	WEEKEND_DOUBLE, 	FIRST_RECHARGE2, 	NEW_FIRST_RECHARGE, 	PASS, 	SEND_GIFT_ACTIVITY, 	SEASON_GIFT_1, 	SEASON_GIFT_2, 	PASS_EXP_BONUS_ACTIVITY, 	NEW_CARD_ACTIVITY_REWARD = 31, 	GIVE_OLD_CARD, 	GIVE_OLD_CARD_UP, 	OLD_CARD_STRATEGY, 	OLD_CARD_ACTIVITY_REWARD, 	OLD_CARD_COLLECTION_REWARD, 	LIGHT_UP_ACTIVITY, 	CHARACTER_FREE_ACTIVITY, 	VOTE_ACTIVITY, 	CHARACTER_SUITE_LOTTERY, 	ANNIVERSARY_REVIEW, 	LIMITLOTTERY_ACTIVITY, 	PINK_LOTTERY_ACTIVITY, 	CHARACTER_UPGRADE_ACTIVITY, 	PASS_LOTTERY_ACTIVITY, 	CHARACTER_DISCOUNT_PACKAGE, 	COMMON_LOGIN_ACTIVITY, 	RESEARCH_LOTTERY_ACTIVITY, 	MYSTERYSTORE_ACTIVITY, 	OLD_MODEL_RESELL_DISCOUNT, } public enum ActivityCollectionType { 	NONE, 	ACTIVITY_LOBBY, 	NEW_CARD_ACTIVITY, 	CHARACTER_ACTIVITY, 	ANNIVERSART_ACTIVITY, 	OLD_CARD_ACTIVITY, 	LOTTERY_ACTIVITY, 	ANNIVERSART_ACTIVITY2, 	ANNIVERSART_ACTIVITY3, } 

执行反序列化:

public static void Main(string[] args) { 	using (FileStream fs = new FileStream(@"D:TextAssetActivityLobby.txt", FileMode.Open, FileAccess.Read, FileShare.Read)) 	{ 		byte[] bytes = new byte[(int)fs.Length]; 		fs.Read(bytes, 0, (int)fs.Length); 		var data = ZeroFormatterSerializer.Deserialize<List<ActivityLobbyInfo>>(bytes); 		Console.WriteLine(data.Count); 		Console.WriteLine(data[0].TabName); 		Console.WriteLine(data[10].TitleName); 		Console.ReadLine(); 	} } 

运行一下,反序列化这部分应该是没问题了。
逃跑吧少年拆包乱码问题的解决

指定格式输出

现在已经可以将数据反序列化成对象,接下来的目标将对象实例转化成一种可读性比较好的格式,比如此前版本游戏保存数据用的csv格式。上NuGet搜搜看有没有用于读写CSV格式的包。
逃跑吧少年拆包乱码问题的解决
好家伙,刚用过C#中最快的序列化器,这儿又有个.Net中最快的JSON、JSV、CSV文本序列化器?那么就决定是你了,ServiceStpublic static void Main(string[] args) { using (FileStream fs = new FileStream(@"D:TextAssetActivityLobby.txt", FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] bytes = new byte[(int)fs.Length]; fs.Read(bytes, 0, (int)fs.Length); var data = ZeroFormatterSerializer.Deserialize<List<ActivityLobbyInfo>>(bytes); using (StreamWriter sw = new StreamWriter(@"D:TextAssetActivityLobby.csv")) { string result = CsvSerializer.SerializeToString<List<ActivityLobbyInfo>>(data); sw.WriteLine(result); } } }

运行成功!问题解决。
逃跑吧少年拆包乱码问题的解决

总结

版权声明:玥玥 发表于 2021-06-16 16:27:05。
转载请注明:逃跑吧少年拆包乱码问题的解决 | 女黑客导航