【unity逆向】一種global-metadata.dat通用dump方案
0x0 前言
0x1 il2cpp源碼分析
在獲取到il2cpp的源代碼后,我們不難看出出,不論是哪個版本的il2cpp,對于global-metadata.dat的加載方法都是不變的
均是調(diào)用vm::MetadataLoader::LoadMetadataFile對global-metadata.dat進行加載。
我們進一步分析,分析vm::MetadataLoader::LoadMetadataFile是個什么邏輯
這個函數(shù)實際上就是將global-metadata.dat加載進內(nèi)存,并返回首地址,隨后,在MetadataCache::Initialize函數(shù)中把返回的地址強制轉(zhuǎn)換為Il2CppGlobalMetadataHeader*類型,不難判斷出:global-metadata.dat被加載進內(nèi)存后,s_GlobalMetadataHeader的值就是global-metadata.dat起始地址.
0x2 在ida中對il2cpp.so進行分析
用ida打開il2cpp.so,等待加載完成,在字串中搜索“global-metadata.dat”,并跳轉(zhuǎn)到其交叉引用函數(shù)上,這樣一來我們直接就定位到了global_metadata.dat的加載函數(shù),即上一段中所提及的MetadataLoader::LoadMetadataFile函數(shù)

此處我們直接祭出f5,得到如下代碼
不難看出,dword_937B008即為源碼中的s_GlobalMetadata,dword_937B00C即為源碼中的s_GlobalMetadataHeader,sub_5EB0496函數(shù)即為MetadataLoader::LoadMetadataFile
0x3 global-metadata.dat文件頭分析
我們隨便打開一個global-metadata.dat文件,并跑一下模板,不難得知:global-metadata.dat文件頭長度為0x110h,起始的4位為魔數(shù)(這個在內(nèi)存中可能會被抹除,我們后面再說),隨后的4位代表了Metadata version(這個version我們不用管它,畢竟我們要的是通殺的腳本)


中間的可以全部忽略,跳到0x108h,從這個位置開始,exportedTypeDefinitionsOffset和exportedTypeDefinitionsCount兩個值與整個global-metadata.dat的文件大小息息相關,我們可以通過將兩值相加得到global-metadata.dat的大小。
此處需要額外注意的是這兩個值的起始位置不一定是0x108h和0x10Ch,還有可能是0x100h和0x104h,這個需要通過exportedTypeDefinitionsCount的值來判斷,如果在0x10C處讀取到的exportedTypeDefinitionsCount的值小于10,那么上述兩個值的起始位置就應該在0x100h和0x104h。
0x4 frida腳本
由于MetadataCache::Initialize函數(shù)僅會在游戲剛進入時被調(diào)用,因此我們需要通過使用frida喚起進程的方式進行hook(你手速如果夠快也可以不用這么弄)
因此我們就可以得到frida的最終運行命令

在0x2板塊中,我們使用ida對libil2cpp.so進行了反匯編分析,得到sub_5EB0496即為MetadataLoader::LoadMetadataFile,所以我們直接對sub_5EB0496函數(shù)進行hook(這個值是不固定的,每個so都不一樣,要具體情況具體分析)
至此,我們就可以得到腳本第一部分的代碼了:

但是實際運行后,我們會發(fā)現(xiàn)進程在剛剛被啟動的時候libil2cpp.so還并未加載,因此我們的腳本會報錯,想解決這個問題只需要使用setInternal設置一下定時執(zhí)行,并使用try catch塊防止報錯導致的腳本退出

以上就是對s_GlobalMetadataHeader的值的獲取,接下來我們對global-metadata.dat的大小進行計算
在0x3板塊中,我們得知想要計算global-metadata.dat的大小需要獲取到exportedTypeDefinitionsOffset和exportedTypeDefinitionsCount兩個值的大小,即讀取s_GlobalMetadataHeader + 0x108h和s_GlobalMetadataHeader + 0x10Ch兩個地址上的int值

綜合以上兩段代碼,我們可以就得出完整的腳本,如下: ?
0x5 后記
其實這個腳本并不能做到完全的通殺,因為還有一部分游戲采取了按需加載,此時使用這種方法導出的global-metadata.dat是不完整的。
填個坑,前面0x3說加載到內(nèi)存中會抹除魔數(shù)(AF 1B B1 FA),這其實是為了防止直接搜索到global-metadata.dat在內(nèi)存中的位置,但是并沒卵用,我們通過hook的防止,不搜索內(nèi)存直接拿到地址并dump,通殺
如果喜歡的話投個幣或者點個贊啥的都行,謝謝各位讀者
參考:
1.il2cpp源代碼 https://github.com/4ch12dy/il2cpp