Unity Reverse Engineering

2022-05-10

筆記關於 Unity Reverse Engineering 的資源。

logo

說明

Il2Cpp

設計 Unity 支援的語言包含 C#,在跨平台的處理使用 Mono,而新的架構採用 Il2Cpp,藉由 Il2CppDumper 可以還原 Il2Cpp 相關的檔案。

Il2CppDumper | GitHub

Asset Extract

用於將圖片、音效、音樂等資源檔匯出的工具。一般情況可以 load 整個資料夾,但特殊情況需要明確的 load file,例如語言檔,會有不同的 Asset List 供分析。

AssetStudio | GitHub

原本的專案已經 Public Archive 可以改為參考 Fork 後仍有再更新的專案:

AssetStudio | GitHub zhangjiequan

常見的資源類別

Type Info
Texture2D 圖片資源,包含 png, tga, jpeg, bmp
Sprite 圖片資源,包含 png, tga, jpeg, bmp
AudioClip 音效資源,包含 mp3, ogg, wav, m4a, fsb
Font 字體資源,ttf, otf
Mesh 遊戲圖形物件,obj
MonoBehaviour json

其他還有 TextAsset, Shader, MovieTexture, VideoClip, Animator

Intermediate Language Decompiler

處理的標的為資料夾當中的 Assembly-CSharp.dll,可以從 C# Intermediate Language 判斷系統的邏輯 (除了工具,還需要大量的耐心研究就是 😥)

可以使用 ILSpy 或者 dnSpy,dnSpy 已經在 GitHub Archive,但其支援字串的搜尋方式,對於搜尋與處理更為方便。

ILSpy | GitHub dnSpy | GitHub

Analysis Round

想要找到 Gaming Data,使用 dnSpy 用 Gaming System 的關鍵字來尋找,例如 Character, Cook, Items 等

找到一個類別為系統名稱加上 Data,例如 CookData.cs,研究類別當中的資料。

發現使用 Read Binary 資料的方式,從 textAsset 存取資料。意識到資料保存成 Binary 格式,所以參考類別讀取 Binary 資料的方式,新建一個 Console Application 使用相似的 Code。

在參考的部分,引入所有 Managed 資料夾當中的 DLL,並且對 CookData.cs 使用與客製。

碰到載入 textAsset 的問題,直接使用 AssetStudio 取出所有的 textAsset,並且用明確路徑的方式進行 Setup

byte[] readText = File.ReadAllBytes(@"C:\temp\TextAsset\CharacterData.bytes");
using (MemoryStream memoryStream = new MemoryStream(readText))
{
  using (BinaryReader binaryReader = new BinaryReader(memoryStream))
  {
    try
    {
      for (; ; )
      {
        GamingData.CharacterData value = default(GamingData.CharacterData);
        value = default(GamingData.CharacterData);
        int count = (int)binaryReader.ReadInt16();
        byte[] readByte = binaryReader.ReadBytes(count);
        value.characterInfo = CharacterData.Getint(readByte);
      }
    }
    catch (EndOfStreamException)
    {
    }
  }
}

語言文字檔也是使用類似的方式讀取,會有相對的 Read 類別,並且資料也是保存在 textAsset 使用 Binary 的方式保存。

資料檔會需要藉由 Id 去對照語言文字檔,這個部份透過 C# 的 Dictionary 使用來完成,一個好用的 Method 是 TryGetValue,可已處理 Id 對照不存在引發的 exception 😀

想要直接透過 UnityEngine 來載入相關的 textAsset,但碰到外部元件無法呼叫的問題 😐

未處理的例外狀況: System.Security.SecurityException: ECall 方法必須封裝在系統模組中。
  於 UnityEngine.Object.FindObjectOfType(Type type)
  於 SingletonMonoBehaviour`1.get_Instance()

而如果搭配 Unity.Engine 使用資源的方式應該為:

CharacterData.Setup(
  SingletonMonoBehaviour<AssetBundleManager>.Instance.LoadAsset<TextAsset>(
    "Binary/CharacterData",
    Extension.BYTES,
    Language.TRADITIONAL_CHINESE
  )
)

使用心得上,發現 dnSpy 對於搜尋很全面,不論是函式名稱、命名空間等 C# 物件都有支援,但缺點是關鍵字類型的查找較不方便,例如 Code 當中的關鍵字,而解決的方法也很簡單,可以直接使用 dnSpy 將 DLL 轉為 Visual Studio sln,如此一來搜尋功能會更方便,關鍵字的搜尋也不成問題。