hexstr / FGOAssetsModifyTool

Fate/GO资源解密工具
448 stars 63 forks source link

BGO部分AssetBundle解密后,无法用UnityPy读取 #78

Closed anpgab closed 1 year ago

anpgab commented 1 year ago

问题概述

使用FGOAssetsModifyTool解密AssetBundle后,部分文件仅能在AssetStudio中正常加载,使用UnityPyUABE加载则报错。

复现

FGO版本

BGO:2.45.0(资源文件为2022.10.31最新版)

UnityPy报错的资源文件:

附件:files.zip(其中 AssetStorage.txtorigin 目录下的 .bin 是从手机提取的加密文件; decrypted 目录下的 .bin 是使用FGOAssetsModifyTool解密后、可在AssetStudio中加载的资源文件。正常/报错的 .bin 文件各提供了几个样例)

相关工具版本

FGOAssetsModifyTool:最新版(512265aUnityPy:1.9.20(win10,python3.8.3) UABE:3.0 beta 1 AssetStudio:0.16.47

复现方法

可能的原因

排查UnityPy代码发现,报错发生在解压UnityFS文件所含block的LZMA stream过程中,是python的lzma库抛的异常。在此之前的过程(UnityFS header解析、block info & directory node解析)都正常,甚至block的LZMA stream prop也正常。

对解密后 .bin 文件进行观察,发现其大小(bin size)与UnityFS header中记录的size(unityfs size)不相符。bin size总比unityfs size大10~20个字节,而且这些字节均为重复的 D2 CE 。另一方面,测试的几个 .bin 文件都只有1个block,所以unityfs size就是「header」+「compressed blocks info bytes」+「compressed block bytes」的总字节数。从UnityPy和AssetStudio源码看,这也是理论上AssetBundle文件的总长度。就是说,解密后 .bin 文件在尾部多出了一些字节。

而且,发现仅unityfs size为奇数.bin 文件会导致UnityFS及UABE报错。就怀疑是FGOAssetsModifyTool解密过程中的padding导致了文件尾部的损坏(可能只坏了一两个字节)。

但这解释不了为何AssetStudio就能正常加载所有解密后的AssetBundle……

个人查证,AssetStudio使用的LZMA库来自7ZIP官方的LZMA SDK(C#版本);而UnityPy依赖python的lzma库(来自xz)。能查到少量关于两者差别的讨论,但个人不熟悉加密这方面的东西,没头绪。

求助

找到FGO运行时实现AssetBundle解密的过程,并与FGOAssetsModifyTool的代码做对照排查,可能最有利于解决问题。但个人一时没有发现是在哪做的……

hexstr commented 1 year ago

当时升级.net 6.0的时候换了解密库,不太会用这玩意儿,解密后没有移除掉padding block,现在手动移除了。

anpgab commented 1 year ago

当时升级.net 6.0的时候换了解密库,不太会用这玩意儿,解密后没有移除掉padding block,现在手动移除了。

然而新commit编译后,在「解析AssetStorage.txt」时就会报错:

Unexpected EOF
   at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream.Fill()
   at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at ICSharpCode.SharpZipLib.GZip.GZipInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(Stream source, Stream destination, Byte[] buffer)
   at ICSharpCode.SharpZipLib.GZip.GZip.Decompress(Stream inStream, Stream outStream, Boolean isStreamOwner)
   at FGOAssetsModifyTool.CatAndMouseGame.MouseHomeMain(Byte[] data, Byte[] home, Byte[] info, Boolean isCompress) in <some_path>\FGOAssetsModifyTool\CatAndMouseGame.cs:line 365

感觉解密后文件尾部并不仅仅是「多出来一部分」,CatAndMouseGame.cs:L339得到的长度与原始文件的长度未必一致。

hexstr commented 1 year ago

更新,这次测试过加密解密都没问题了

anpgab commented 1 year ago

更新,这次测试过加密解密都没问题了

感谢,现在解密后UnityPy能正常读取,P图方便多了 (之前还真只有lzma stream的最后一个字节是坏的🤣