Unity手游BlueArchive蔚蓝档案剧情文本提取

查看 86|回复 9
作者:k96e   
一直没见着有人做,以为是啥很难的活,实际上难度不大。  
下手的是国际服(因为一下子就能解出五种语言的脚本),剧情是能不换包体动态更新的,所以肯定得在数据目录下找。  
翻目录找到可疑的文件Android/data/com.nexon.bluearchive/files/PUB/Resource/Preload/TableBundles下的ExcelDB.db和Excel.zip  
先复制出来再说,简单看一下Excel.zip,似乎全是角色和关卡数据之类的,和咱们要找的剧情文本没关系。  
转战ExcelDB,SQLiteStudio打开


{019CD806-0AE9-4607-9BFC-D279BDE734F3}.png (86.48 KB, 下载次数: 0)
下载附件
2024-11-20 21:35 上传

欸,ScenarioScriptDBSchema,这表名一看就对劲了,再看一眼数据


{DD57D1F4-979A-4C75-9498-35C7543747F1}.png (118.4 KB, 下载次数: 0)
下载附件
2024-11-20 21:38 上传

更对劲了
接下来就是这个Bytes怎么解析的问题。
你要是现在能看出来这是flatbuffers,那此贴到这就完结了,但是铸币楼主当时就愣是没看出来,还以为是啥自行实现的序列化方法。
然后就对于这类U3D il2cpp的游戏,公式化的提取libil2cpp.so和global-metadata.dat,然后用Il2CppDumper反编译
[Shell] 纯文本查看 复制代码..\Il2CppDumper.exe libil2cpp.so global-metadata.dat ..\output
运行完先别急着开IDA,打开dump.cs,搜索ScenarioScriptExcel,直接就能找到结构体定义


{61B4D716-7A56-4996-B1D7-5A352C876ED7}.png (210.66 KB, 下载次数: 0)
下载附件
2024-11-20 21:53 上传

(IFlatbufferObject善意提醒大家这是flatbuffers)
根据定义,写出schema文件(fbs文件):
[C#] 纯文本查看 复制代码namespace MX.Data.Excel;
table ScenarioScriptExcel {
  GroupId:long;
  SelectionGroup:long;
  BGMId:long;
  Sound:string;
  Transition:uint;
  BGName:uint;
  BGEffect:uint;
  PopupFileName:string;
  ScriptKr:string;
  TextJp:string;
  TextTh:string;
  TextTw:string;
  TextEn:string;
  VoiceId:uint;
  TeenMode:bool;
}
root_type ScenarioScriptExcel;
安装flatbuffers的schema编译器flatc,运行
[Shell] 纯文本查看 复制代码flatc --python ScenarioScriptExcel.fbs
得到用来反序列化的python代码,然后写个脚本
[Python] 纯文本查看 复制代码import flatbuffers
import MX.Data.Excel.ScenarioScriptExcel as ScenarioScriptExcel
import json
import sqlite3
conn = sqlite3.connect('../ExcelDB.db')
cursor = conn.cursor()
d = cursor.execute("select * from ScenarioScriptDBSchema")
l = list(d)
datas = []
def read_bin_file(file_path):
    with open(file_path, 'rb') as f:
        return f.read()
def parse_scenario_script(buffer):
    buf = bytearray(buffer)
    fb = flatbuffers.Builder(0)
    fb.Bytes = buf
    scenario = ScenarioScriptExcel.ScenarioScriptExcel.GetRootAsScenarioScriptExcel(buf, 0)
    return scenario
def process(buffer):
    global datas
    scenario = parse_scenario_script(buffer)
    datas.append({
        "GroupId": scenario.GroupId(),
        "SelectionGroup": scenario.SelectionGroup(),
        "BGMId": scenario.Bgmid(),
        "Transition": scenario.Transition(),
        "BGName": scenario.Bgname(),
        "BGEffect": scenario.Bgeffect(),
        "ScriptKr": scenario.ScriptKr().decode('utf-8'),
        "TextJp": scenario.TextJp().decode('utf-8'),
        "TextTh": scenario.TextTh().decode('utf-8'),
        "TextTw": scenario.TextTw().decode('utf-8'),
        "TextEn": scenario.TextEn().decode('utf-8'),
        "VoiceId": scenario.VoiceId(),
        "TeenMode": scenario.TeenMode()
    })
for i in l:
    process(i[1])
with open("scenario_script.json", "w", encoding="utf-8") as f:
    json.dump(datas, f, ensure_ascii=False, indent=4)
完事


{CBAF6385-CBEE-4D46-9A71-DC0BE3A53766}.png (298.08 KB, 下载次数: 0)
下载附件
2024-11-20 22:05 上传

下载次数, 文本

hhao7780   

不懂也来看看
rnaapp   

很厉害的感觉,旺德福
Jiu9Hao   

经验学习了,感谢分享
hayatecn   

有没有原神的?
xieyinghao   

很厉害的大佬,666,感谢恩人
无奈的地刺王   

感谢分享,学习了
zyh5028   

学习了,感谢
xy1687   

感谢分享,学习了
LHHK   

感谢分享,学习了
您需要登录后才可以回帖 登录 | 立即注册

返回顶部