永劫无间 bundle 脚本 COMP_FIX/UNCOMP_FIX 值计算QuickBMS

快来注册~

您需要 登录 才可以下载或查看,没有账号?注册账号

x
QQ20260222-182419.png

如何计算《永劫无间》bundle文件中 DELTA 对应的 COMP_FIX/UNCOMP_FIX 值,本质是找到「文件头记录的大小」与「实际文件大小」的差值,再反向推导需要修正的块大小参数。下面我会用新手能看懂的方式,拆解计算逻辑和实操步骤。
  1. # Naraka: Bladepoint – Unity bundle fix / decrypt (v7-bms, 2025-08-08)
  2. # Works with any recent QuickBMS, no -c switch needed
  3. # 注释:脚本版本/适用范围,无需加-c参数运行

  4. set AES_KEY binary "\xE8\x2A\xE4\x9B\x5C\x3D\xA8\xB4\x1F\x4C\x3E\x3D\x5D\xE2\xB8\xF1"
  5. # 核心:设置解密用的AES密钥(16字节ECB模式),是破解加密bundle的关键
  6. set MAGIC_FIX string "UnityFS"
  7. # 定义修复后文件头的标准标识(UnityFS是Unity资源包的标准魔数)

  8. math OVERRIDE = 0
  9. math COMP_FIX = 0
  10. math UNCOMP_FIX = 0
  11. # 初始化三个数学变量,用于后续计算修复参数

  12. endian big
  13. # 设置字节序为大端(匹配游戏资源的存储格式)
  14. get HEAD long
  15. # 读取文件前4字节作为文件头标识
  16. if HEAD != 0x151E1C0D && HEAD != 0x556E6974
  17.     print "Not a Naraka encrypted/fixed bundle"
  18.     cleanexit
  19. endif
  20. # 判断是否是永劫无间的加密bundle:不是则直接退出

  21. # ---------- 自动解密 ----------
  22. savepos BACK
  23. # 保存当前读取位置(用于解密后回退)
  24. get SIZE asize
  25. # 获取文件总大小
  26. getdstring TEST 16
  27. # 读取前16字节测试是否为全0(加密bundle的特征)
  28. if TEST == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  29.     encryption aes_ecb AES_KEY
  30.     # 启用AES-ECB加密模式(实际是解密)
  31.     log MEMORY_FILE 0 SIZE
  32.     # 把整个文件读入内存并解密
  33.     encryption ""
  34.     # 关闭加密模式
  35.     get NAME filename
  36.     string NAME p "%s_dec" NAME
  37.     # 生成新文件名:原文件名+_dec(比如xxx.bundle → xxx_dec.bundle)
  38.     log NAME 0 SIZE MEMORY_FILE
  39.     # 输出解密后的文件
  40.     print "Decrypted -> %NAME%. Run script again on the decrypted file."
  41.     cleanexit
  42. endif
  43. encryption ""
  44. goto BACK
  45. # ------------------------------

  46. # 解密完成后,第二次运行脚本会进入这里(修复文件头)
  47. get SIGN string         # 读取UnityFS标识
  48. get VER long            # 读取Unity版本号
  49. get DUMMY string        # 跳过无用数据
  50. get SIZE8 longlong      # 读取文件头记录的总大小
  51. savepos HDR_END         # 保存文件头结束位置

  52. get BLOCKS_COMPRESSED long    # 读取压缩块数量
  53. get BLOCKS_UNCOMPRESSED long  # 读取未压缩块数量
  54. get COMP_FLAG long            # 读取压缩标识

  55. get FSIZE asize               # 获取实际文件大小
  56. math DELTA = SIZE8
  57. math DELTA -= FSIZE           # 计算记录大小与实际大小的差值

  58. # 根据差值匹配修复参数(游戏更新后差值会变,需更新脚本)
  59. if DELTA == 0
  60.     print "Bundle already fixed"
  61.     cleanexit
  62. elif DELTA == 0x1A
  63.     math COMP_FIX = 180
  64.     math UNCOMP_FIX = 170
  65. elif DELTA == 0x16
  66.     math COMP_FIX = 202
  67.     math UNCOMP_FIX = 202
  68. elif DELTA == 0x14
  69.     math COMP_FIX = 164
  70.     math UNCOMP_FIX = 156
  71. elif DELTA == 0x1E
  72.     math COMP_FIX = 240
  73.     math UNCOMP_FIX = 230
  74. else
  75.     print "Unknown delta 0x%DELTA%, please wait for script update"
  76.     cleanexit
  77. endif

  78. # 修复文件头的压缩/未压缩块参数
  79. if SIGN != "UnityFS"
  80.     math BLOCKS_COMPRESSED -= COMP_FIX
  81.     math BLOCKS_UNCOMPRESSED -= UNCOMP_FIX
  82.     set MAGIC string "UnityFS"
  83. else
  84.     math BLOCKS_COMPRESSED += COMP_FIX
  85.     math BLOCKS_UNCOMPRESSED += UNCOMP_FIX
  86.     set MAGIC binary "0x151E1C0D0D2321"
  87. endif

  88. # 写入修复后的文件头
  89. goto 0                   # 回到文件开头
  90. put MAGIC string         # 写入标准UnityFS标识
  91. goto HDR_END             # 跳回文件头结束位置
  92. put BLOCKS_COMPRESSED long  # 写入修复后的压缩块数量
  93. put BLOCKS_UNCOMPRESSED long # 写入修复后的未压缩块数量
  94. print "Bundle header fixed successfully"
复制代码


一、先理解核心概念(计算的前提)在开始计算前,先明确几个关键变量的含义:
变量名
含义

SIZE8
bundle文件头中记录的文件总大小(脚本里用get SIZE8 longlong读取)

FSIZE
bundle文件实际的磁盘大小(脚本里用get FSIZE asize读取)

DELTA
差值 = SIZE8 - FSIZE(文件头记录的大小 - 实际大小)

COMP_FIX/UNCOMP_FIX
要计算的修正值,用于调整「压缩块/未压缩块」的数量,让文件头符合UnityFS标准

二、计算的核心逻辑永劫无间的bundle文件被加密/篡改后,SIZE8(记录大小)和FSIZE(实际大小)会不一致,且「压缩块/未压缩块数量」被人为偏移了一个固定值(就是COMP_FIX/UNCOMP_FIX)。
计算的本质是:找到这个被偏移的固定值,反向修正回去
具体逻辑分两步:
  • 先算出DELTA值;
  • 用「正常的UnityFS文件」作为参考,对比「被篡改的文件」的块数量,差值就是COMP_FIX/UNCOMP_FIX。
三、实操计算步骤(手把手教)你需要准备2个工具:
  • QuickBMS(带调试功能)或 010 Editor(二进制编辑器,推荐,可视化更强);
  • 一个「已知可正常解析的UnityFS bundle文件」(作为参考,比如其他Unity游戏的正常bundle)。
步骤1:计算DELTA值(基础)首先拿到你要处理的Naraka bundle文件,先算出DELTA:
  • 用010 Editor打开该bundle文件;
  • 查看文件实际大小:右键文件→属性,记录FSIZE(比如102400字节);

  • 读取SIZE8(文件头记录的大小):
    • UnityFS格式的bundle文件头结构固定,SIZE8通常在「UnityFS标识 + 版本号」之后的8字节位置(偏移量约0x18);
    • 在010 Editor中跳转到偏移0x18,读取8字节的十六进制值,转换为十进制,就是SIZE8;
  • 计算DELTA = SIZE8 - FSIZE(比如SIZE8=102426,FSIZE=102400,则DELTA=26(0x1A))。
步骤2:计算COMP_FIX/UNCOMP_FIX(核心)这一步需要对比「正常UnityFS文件」和「Naraka篡改文件」的块数量,找到偏移值:
子步骤1:读取Naraka篡改文件的块数量
  • 用010 Editor打开Naraka的bundle文件(已解密但未修复的_dec.bundle);

  • 跳转到「块数量」的偏移位置:
    • UnityFS文件头中,BLOCKS_COMPRESSED(压缩块数量)在偏移0x28位置(4字节);
    • BLOCKS_UNCOMPRESSED(未压缩块数量)在偏移0x2C位置(4字节);
  • 记录这两个值:比如读取到BLOCKS_COMPRESSED=200,BLOCKS_UNCOMPRESSED=190。
子步骤2:读取正常UnityFS文件的块数量
  • 找一个正常的UnityFS bundle文件(比如从其他Unity游戏提取的、AssetStudio能直接识别的);

  • 用同样的方法,读取它的BLOCKS_COMPRESSED和BLOCKS_UNCOMPRESSED:
    • 比如正常文件的BLOCKS_COMPRESSED=20,BLOCKS_UNCOMPRESSED=20。

子步骤3:计算修正值修正值 = 「Naraka篡改文件的块数量」 - 「正常文件的块数量」(或反向,取决于SIGN是否为UnityFS):
  • 如果文件头的SIGN(标识)不是 "UnityFS"(说明被篡改):
COMP_FIX = Naraka_COMP - 正常_COMP
UNCOMP_FIX = Naraka_UNCOMP - 正常_UNCOMP
示例:Naraka_COMP=200,正常_COMP=20 → COMP_FIX=180;Naraka_UNCOMP=190,正常_UNCOMP=20 → UNCOMP_FIX=170(对应脚本里DELTA=0x1A的情况)。
  • 如果文件头的SIGN "UnityFS"(极少见):
COMP_FIX = 正常_COMP - Naraka_COMP
UNCOMP_FIX = 正常_UNCOMP - Naraka_UNCOMP
步骤3:验证计算结果把算出的COMP_FIX/UNCOMP_FIX写入脚本,替换对应DELTA的分支:
elif DELTA == 0xXX  # 你算出的新DELTA值    math COMP_FIX = 你计算的修正值    math UNCOMP_FIX = 你计算的修正值然后用QuickBMS运行脚本,修复bundle文件:
  • 若修复后AssetStudio能正常加载资源 → 计算正确;
  • 若仍无法加载 → 检查「块数量偏移位置」是否读错,或正常参考文件的Unity版本是否匹配(永劫无间用的是Unity 2021+)。
四、简化版实操技巧(新手替代方案)如果不想手动读二进制,也可以用QuickBMS的调试模式快速获取关键值:

  • 打开CMD,进入QuickBMS目录,运行调试命令:

      quickbms.exe -d naraka_fix.bms 你的_dec.bundle 输出目录  (-d是调试模式,会输出所有变量的取值);

  • 在调试日志中找到:

      SIZE8 = [数值]FSIZE = [数值]DELTA = [数值]BLOCKS_COMPRESSED = [数值]BLOCKS_UNCOMPRESSED = [数值]
  • 找一个正常的UnityFS bundle,用同样的调试命令读取它的BLOCKS_COMPRESSED/BLOCKS_UNCOMPRESSED;
  • 按步骤2的公式计算修正值即可。
五、常见坑点(避免计算错误)
  • 字节序问题:UnityFS用「小端序」存储数值,010 Editor中要确认「字节序设置为Little Endian」,否则读取的SIZE8/块数量会是错的;
  • 文件未解密:必须先对Naraka的bundle解密(生成_dec.bundle),再计算,加密状态下的数值无意义;
  • Unity版本匹配:参考的正常bundle文件需和永劫无间的Unity版本一致(2021.x),否则文件头结构不同;
  • DELTA为负数:若DELTA = SIZE8 - FSIZE < 0,说明文件被截断,需重新解包PAK获取完整的bundle文件。
总结
  • 计算的核心是:先算DELTA = 记录大小(SIZE8) - 实际大小(FSIZE),再对比「篡改文件」和「正常UnityFS文件」的块数量,差值就是COMP_FIX/UNCOMP_FIX;
  • 实操优先用010 Editor(可视化)或QuickBMS调试模式(直接输出变量),避免手动算错;
  • 关键前提:bundle文件需先解密,且参考的正常文件要匹配Unity版本(2021+)。

[size=102400,则DELTA=26(0x1A))。&quot;},&quot;attribs&quot;:{&quot;0&quot;:&quot;*0+2*0*1+l*0+3*0*1+c*0+1*0*1+c*0+2*0*1+8*0+8&quot;}},&quot;apool&quot;:{&quot;numToAttrib&quot;:{&quot;0&quot;:[&quot;author&quot;,&quot;4431501448972572&quot;],&quot;1&quot;:[&quot;inlineCode&quot;,&quot;true&quot;]},&quot;nextNum&quot;:2}},&quot;type&quot;:&quot;ordered&quot;}},&quot;NjXWfOQvgdlMNAczRYv5kc5elko&quot;:{&quot;id&quot;:&quot;NjXWfOQvgdlMNAczRYv5kc5elko&quot;,&quot;snapshot&quot;:{&quot;align&quot;:&quot;&quot;,&quot;author&quot;:&quot;4431501448972572&quot;,&quot;children&quot;:[],&quot;comments&quot;:[],&quot;hidden&quot;:false,&quot;locked&quot;:false,&quot;parent_id&quot;:&quot;M7mEfIigedRb4jcyylTctcsoncc&quot;,&quot;revisions&quot;:[],&quot;text&quot;:{&quot;initialAttributedTexts&quot;:{&quot;text&quot;:{&quot;0&quot;:&quot;步骤2:计算COMP_FIX/UNCOMP_FIX(核心)&quot;},&quot;attribs&quot;:{&quot;0&quot;:&quot;*0+t&quot;}},&quot;apool&quot;:{&quot;numToAttrib&quot;:{&quot;0&quot;:[&quot;author&quot;,&quot;4431501448972572&quot;]},&quot;nextNum&quot;:1}},&quot;type&quot;:&quot;heading4&quot;}},&quot;WVCBffEEPdI4oWc1nZANQIoH3cj&quot;:{&quot;id&quot;:&quot;WVCBffEEPdI4oWc1nZANQIoH3cj&quot;,&quot;snapshot&quot;:{&quot;align&quot;:&quot;&quot;,&quot;author&quot;:&quot;4431501448972572&quot;,&quot;children&quot;:[],&quot;comments&quot;:[],&quot;hidden&quot;:false,&quot;locked&quot;:false,&quot;parent_id&quot;:&quot;M7mEfIigedRb4jcyylTctcsoncc&quot;,&quot;revisions&quot;:[],&quot;text&quot;:{&quot;initialAttributedTexts&quot;:{&quot;text&quot;:{&quot;0&quot;:&quot;这一步需要对比「正常UnityFS文件」和「Naraka篡改文件」的块数量,找到偏移值:&quot;},&quot;attribs&quot;:{&quot;0&quot;:&quot;*0+18&quot;}},&quot;apool&quot;:{&quot;numToAttrib&quot;:{&quot;0&quot;:[&quot;author&quot;,&quot;4431501448972572&quot;]},&quot;nextNum&quot;:1}},&quot;type&quot;:&quot;text&quot;}},&quot;NbzzfpegzdnBC6cMo8xqAeShJ0e&quot;:{&quot;id&quot;:&quot;NbzzfpegzdnBC6cMo8xqAeShJ0e&quot;,&quot;snapshot&quot;:{&quot;align&quot;:&quot;&quot;,&quot;author&quot;:&quot;4431501448972572&quot;,&quot;children&quot;:[],&quot;comments&quot;:[],&quot;hidden&quot;:false,&quot;locked&quot;:false,&quot;parent_id&quot;:&quot;M7mEfIigedRb4jcyylTctcsoncc&quot;,&quot;revisions&quot;:[],&quot;text&quot;:{&quot;initialAttributedTexts&quot;:{&quot;text&quot;:{&quot;0&quot;:&quot;子步骤1:读取Naraka篡改文件的块数量&quot;},&quot;attribs&quot;:{&quot;0&quot;:&quot;*0+l&quot;}},&quot;apool&quot;:{&quot;numToAttrib&quot;:{&quot;0&quot;:[&quot;author&quot;,&quot;4431501448972572&quot;]},&quot;nextNum&quot;:1}},&quot;type&quot;:&quot;heading5&quot;}},&quot;ClSmfqNUhdGhw7cT9g3FlKvfRdJ&quot;:{&quot;id&quot;:&quot;ClSmfqNUhdGhw7cT9g3FlKvfRdJ&quot;,&quot;snapshot&quot;:{&quot;align&quot;:&quot;&quot;,&quot;author&quot;:&quot;4431501448972572&quot;,&quot;children&quot;:[],&quot;comments&quot;:[],&quot;hidden&quot;:false,&quot;locked&quot;:false,&quot;parent_id&quot;:&quot;M7mEfIigedRb4jcyylTctcsoncc&quot;,&quot;revisions&quot;:[],&quot;seq&quot;:&quot;1&quot;,&quot;text&quot;:{&quot;initialAttributedTexts&quot;:{&quot;text&quot;:{&quot;0&quot;:&quot;用010]
免责声明:
资源盒论坛发布的一切资源、模型和注册信息及软件的源码教程仅限用于学习和研究目的;
不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。
本站资源来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。
如果您喜欢该程序/源文件,请支持正版软件,购买/注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。
若本站侵犯了您的权益请联系站长进行删除处理E-mail:190183740@qq.com;
这个家伙很懒,没有设置签名~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

知源盒集 3D 打印资源、实用工具与网创项目于一体的综合分享平台。

联系客服 进入论坛