记录一次逆向Assembly-CSharp.dll解密AssetBundle提取unity游戏资源

在游戏_Data\StreamingAssets\...目录下找到.bundle资源文件,打开一看发现是加密的

这样的文件直接丢进AssetStudio根本没法提取,会一直报数组维度超范围的。

平时到这一步就直接放弃了,但是正赶上52论坛开放注册,等10分钟的时间在52学习了各个大佬的思路,突然就觉得我上我也行了。

看完这位大佬https://www.52pojie.cn/thread-1631028-1-1.html的流程后

得知在游戏_Data\Managed 目录下有Assembly-CSharp.dll文件,属于mono类型,游戏逻辑在 Assembly-CSharp.dll 和其它同路径下的文件里,此时用 dnspy 逆向。

下载个dnspy,把Assembly-CSharp.dll往里一拖,呦呵还真有东西。

然后按照思路要找到切入点,这里的切入点就是从.bundle读取AssetBundle、解密、解包从中提取资源的过程。

无需关注如何解密和解密的过程,我们要的只是解密后得到的结果。所以需要在unity引擎读取.bundle文件并解密之后,拿到这个解密后的东西(后面知道了它是Stream类型的)

在dnspy保存代码,用vscode打开,这样搜索比较方便。

搜索一下AssetBundle,发现一个class EncryptedAssetBundleProvider中有很多“AssetBundle”字段,其中的属性和方法如下图

发现它还有从网络加载AssetBundle的功能,在方法BeginOperation()中

private void BeginOperation()
        {
            string text = m_ProvideHandle.ResourceManager.TransformInternalId(m_ProvideHandle.Location);
            if (File.Exists(text) || (Application.platform == RuntimePlatform.Android && text.StartsWith("jar:")))
            {
                m_RequestOperation = _0082_0083_008F_009A_0097_0088_0089_0089_0096._008D_0099_0085_009E_0080_009D_0092_0081_0080(new _0093_0093_0085_0083_0096_008A_0098_0093_008A(text, FileMode.Open, FileAccess.Read));
                m_RequestOperation.completed += LocalRequestOperationCompleted;
            }
            else if (ResourceManagerConfig.ShouldPathUseWebRequest(text))
            {
                UnityWebRequest unityWebRequest = CreateWebRequest(m_ProvideHandle.Location);
                unityWebRequest.disposeDownloadHandlerOnDispose = false;
                m_WebRequestQueueOperation = _009B_008D_0092_008B_0083_0082_0090_0081_008E._009C_009E_009D_008B_0098_0088_0098_009D_0098(unityWebRequest);
                if (m_WebRequestQueueOperation._008B_007F_0081_0082_0084_008B_0092_0091_008B)
                {
                    m_RequestOperation = m_WebRequestQueueOperation._0093_009A_008B_008E_0095_0093_0097_008F_0091;
                    m_RequestOperation.completed += WebRequestOperationCompleted;
                    return;
                }
                _0090_0088_007F_009A_008E_009A_0093_0097_008B webRequestQueueOperation = m_WebRequestQueueOperation;
                webRequestQueueOperation._0097_0092_008F_0081_0088_009C_0099_0097_0090 = (Action<UnityWebRequestAsyncOperation>)Delegate.Combine(webRequestQueueOperation._0097_0092_008F_0081_0088_009C_0099_0097_0090, (Action<UnityWebRequestAsyncOperation>)delegate(UnityWebRequestAsyncOperation asyncOp)
                {
                    m_RequestOperation = asyncOp;
                    m_RequestOperation.completed += WebRequestOperationCompleted;
                });
            }
            else
            {
                m_RequestOperation = null;
                m_ProvideHandle.Complete<EncryptAssetBundleResource>(null, status: false, new Exception($"Invalid path in AssetBundleProvider: '{text}'."));
            }
        }

可以看到判断的第一个分支是从本地加载AssetBundle

m_RequestOperation = _0082_0083_008F_009A_0097_0088_0089_0089_0096._008D_0099_0085_009E_0080_009D_0092_0081_0080(new _0093_0093_0085_0083_0096_008A_0098_0093_008A(text, FileMode.Open, FileAccess.Read));
m_RequestOperation.completed += LocalRequestOperationCompleted;

从变量和函数名推测第二行是加载成功后的操作,那么第一行就是加载这个动作本身了

找到第一行中方法定义的位置

这个方法中又调用了上一个方法,在类中插入一个属性作为文件名,在方法中插入一段代码(12-16行,33行)实现把Stream存储到文件的功能。当游戏引擎加载AssetBundle时会多次执行5-9行我们插入的代码。

插入代码的方式一言难尽,只能通过il码的方式编写。你可能需要安装visual studio来编写C#代码,编译再反编译来查看il码,并且这可能需要一些计算机和编程基础。

这里放上我碰到的一个问题,dnspy一直报index超范围,后来发现是操作码写错了:

对于操作码ldarg:如果是实例方法的话ldarg.0加载的是对象本身,也就是this,ldarg.1加载的才是方法的第一个参数;如果是静态方法,ldarg.0就是传入的第一个参数。

il码的教程https://www.cnblogs.com/cdaniu/p/15865337.html

总之,插入的这段代码在游戏启动时被执行了,解密后的数十个AssetBundle被保存到了指定位置,再用AssetStudio就可以完美提取了!

附上修改后的Assembly-CSharp.dll文件,覆盖Managed目录中的文件。再次启动游戏时,AssetBundle就会被保存到C:\temp目录下了。

解包过程中还参考了下列文章或教程

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇