1 branches0 tags
SShih-Te Hsiao公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
03432434 hours ago
  • ClaudeDocs/
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • hohohololive/
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • .gitignore
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • compare_swing.py
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • extract_swing.py
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • LICENSE
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • README.md
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
  • sim_swing.py
    公開版:格式轉換工具與逆向紀錄,不含解密 完整版的解密層不在這裡,而且這不是疏漏。原本的計畫是「拿掉金鑰、 留下演算法」,但那個切法在這裡不成立:金鑰是從資產名推導出來的, 推導程序本身就是金鑰,沒有獨立的秘密可以拿掉。實作裡唯一的魔術 常數是單一位元組,已知明文就寫在檔頭,256 種可能是微秒級的窮舉 ——只遮那個常數等於什麼都沒遮,卻會給假的安心感。所以整層移除。 移除:crypto.py、REF_ALGORITHM_MATH.md、RE_NOTES_CRYPTO.md、 OVERVIEW.md §3 的虛擬碼、decrypt-bundle/decrypt-audio 兩個子指令、 整個 scripts/(混著 Frida 解密 hook)、兩份綁死本機路徑的代理工單。 保留:格式解析的全部(catalog、AssetBundle 抽取、mesh/骨架/材質、 glTF 轉檔、Live2D 與 3D 動作解碼)、離線彈簧骨物理,以及 8 份逆向 日誌——包含走過的死路與後來被推翻的結論。 理由與免責聲明見 README.md。 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01RRycU1U8ByjzQ5pmzcPJmf
    4 hours ago
README.md

hohohololive — 公開版

Unity 手遊資源系統的逆向工程紀錄與格式轉換工具

命名致敬 sssekai


⚠️ 先讀這段:這是刻意閹割過的版本

這個版本不包含解密。 完整版有,公開版沒有,而且這不是疏漏,是刻意的。

移除了什麼

移除 內容
hohohololive/crypto.py 金鑰衍生與解密實作
ClaudeDocs/REF_ALGORITHM_MATH.md 演算法的完整數學規格
ClaudeDocs/RE_NOTES_CRYPTO.md 解密過程的逐步紀錄
ClaudeDocs/OVERVIEW.md §3 的虛擬碼 可直接實作的填充順序、雜湊種子、白化步驟
CLI 的 decrypt-bundle / decrypt-audio 兩個直接解密的子指令
scripts/ 整個目錄 混著 Frida 解密 hook 與一次性診斷腳本,逐支審不划算
ClaudeDocs/GEMINI_TASK.mdDISPATCH_SUPERVISOR.md 給代理跑的工單,綁死本機路徑、引用未收錄的腳本

為什麼不是「只拿掉金鑰,留下演算法」

一開始的計畫是這樣,但這個切法在這裡不成立,值得寫下來:

一般的密碼系統是「公開演算法 + 秘密金鑰」,遮掉金鑰就夠了(Kerckhoffs 原則)。 這裡不是。 這套機制的金鑰是從資產名推導出來的——輸入是檔名,輸出是金鑰表。 推導程序本身就是金鑰,沒有一個獨立的秘密可以拿掉。

而原始實作裡唯一的魔術常數,是一個單一位元組的雜湊種子。在:

  • 已知明文就寫在檔頭(UnityFSQUAVMAGIC 都是固定前綴)
  • 演算法結構已公開

這兩個條件下,256 種可能的窮舉是微秒級的事。只遮那個常數,降低的工作量是零, 卻會做出一個「看起來遮過、其實沒有」的東西——那比兩個極端都糟,因為它給假的安心感。

所以整個解密層一起移除,而不是做部分遮蔽。

法律上的考量

台灣著作權法 §80-2 第二項禁止提供「主要用於規避防盜拷措施之設備、器材、零件、 技術或資訊」。注意「資訊」二字——它涵蓋的不只是可執行的程式碼,也涵蓋一份 寫得夠清楚、讀完就能自行實作的規格文件。被移除的那幾份文件正是如此。

同條第三項確實有「為達成資訊間之相互操作性所為之還原工程」的例外,但該例外 一般理解為涵蓋進行還原工程,而非公開發佈規避方法。這是灰色地帶,而 作者不是律師,因此採取保守作法。


保留了什麼(而且它們本身就有用)

留下來的是格式解析那一半:輸入是已經解密的資料,輸出是通用格式。這部分 的性質是互通性工作——把封閉格式轉成開放格式,讓資料能在別的工具裡使用。

hohohololive/
├── catalog.py            octo 目錄解析 (hash / address / size / objectName)
├── extract.py            AssetBundle 抽取,含跨 bundle 的 CAB 依賴解析
├── model3d.py            3D 模型抽取 (mesh / 貼圖 / 骨架 / 材質)
├── gltf.py               Unity 頂點串流 → 有綁定的 glTF 2.0 (含 morph target)
├── motion3d.py           mot_define_* 動作曲線解碼 (CRC32 名稱還原)
├── animglb.py            把動作併進模型 .glb
├── live2d_motion.py      Live2D 動作 → motion3.json (三次 Bezier 轉檔)
├── live2d_expression.py  Live2D 表情 → exp3.json
├── live2d_physics.py     Live2D 物理 → physics3.json
└── cdn.py                以 objectName 從 CDN 取資源

sim_swing.py              離線重現 ActorSwing 彈簧骨(純 numpy/scipy)
compare_swing.py          模擬 vs 遊戲真值的逐幀角度比對
extract_swing.py          從 bundle 抽彈簧骨參數

彈簧骨那三支放在根目錄而不是套件裡,是因為文件(RE_NOTES_AVATAR.md) 大量引用它們的檔名。它們不碰解密,但物理還沒解完——誤差仍略差於 「完全不做」,細節見 ClaudeDocs/HANDOFF.md。收錄未完成的東西是刻意的: 沒解完的過程和解完的一樣值得讀。

CLI 子指令:catalog-parse unpack-octo build-live2d extract-3d extract-motions-3d merge-motion extract-motions extract-expressions

輸入必須是已解密的 AssetBundle。 餵密文進去不會產生垃圾:PlaintextGate 會跳過它、計數,並在指令結束時說明一次。

(它一開始寫成「遇到密文就中止」,那是錯的——這些檢查全在批次迴圈裡, 而 SystemExit 不是 Exception 的子類,外層的 except Exception 攔不住, 一個檔案就會丟掉後面所有位址。跳過並統計才是對的形狀。)

文件

ClaudeDocs/ 是完整的逆向報告,以「每章回答一個問題」的方式寫成,包含走過的 死路與後來被推翻的結論——那些才是重點。

  • OVERVIEW.md — 主報告(§3 的演算法虛擬碼已移除,形狀描述與過程紀錄保留)
  • RE_NOTES_3D.md / RE_NOTES_LIVE2D.md / RE_NOTES_AVATAR.md — 格式逆向的逐步紀錄
  • REF_CHARACTER_ROSTER.md — 角色名冊與資產統計
  • NEXT_STEPS.md / HANDOFF.md — 未完成的部分

一篇關於這次逆向過程的文章:逆向一個 Unity 6 手遊時,我四次以為自己成功了


免責聲明

  • 本庫僅包含作者原創的逆向研究文檔與格式轉換工具。
  • 不包含任何遊戲資源。 遊戲的音效、影片、模型、貼圖、Live2D 資產等, 著作權均屬其發行商所有,本庫中沒有任何一個 byte 的遊戲素材,也不提供取得管道。
  • 本庫不包含規避技術保護措施的實作或規格。
  • 本專案供學習、互通性研究、個人備份用途。使用者須自行確認其使用方式 符合所在地法律與相關服務條款;作者不對任何使用行為負責。
  • 工具本身以 MIT 授權釋出(見 LICENSE),此授權僅及於作者原創之程式碼與文件。
  • 本專案與遊戲發行商無任何隸屬、合作或背書關係。

授權

MIT — 見 LICENSE