逆向某游戲加密文本——IL2CPP
????今天來解密一下一款名叫圣騎士莉卡的游戲。游戲的文本以及存檔都做了加密,而且游戲打包用的IL2CPP這就加大了逆向的難度(一般用IL2CPP打包的游戲比較容易勸退)。
不過對于我這種沒事就搞搞Unity逆向的人來說其實(shí)跟Mono差不多,只是增加了一點(diǎn)分析難度。
????首先老套路,先用IL2CppDumper對腳本進(jìn)行初步的解析。一般來說,沒動(dòng)過手腳的腳本IL2CppDumper自動(dòng)分析就行了。分析完后,主要用到dump.cs 和 stringliteral.json 這兩個(gè)文件。dump.cs 用來分析腳本的大致邏輯,里面包含所有類和方法的基本信息。
當(dāng)然,也可以用dnspy直接分析DummyDll目錄下生成的C#腳本。
stringliteral.json 則包含了腳本內(nèi)部會(huì)用到的字符串信息(需要在后續(xù)IDA分析中用到)。

本次主要是分析加密解密的方法,前期的方法的定位過程就大致略過了。
定位:
????首先要定位加密解密腳本,這里我發(fā)現(xiàn),如果直接把部分游戲文本刪掉的話,游戲依然能運(yùn)行,缺失的文本位置,全部都會(huì)由索引用的字段代替。而且在游戲存檔位置的log文件中,會(huì)看到報(bào)錯(cuò)。
????通過報(bào)錯(cuò)信息,可以大致得到加載文本涉及到的類和方法。
于是通過一系列分析,最終定位到了Crypt這個(gè)類。

????可以看到,該類有兩個(gè)私有字符串類型的字段,pw和salt,非常明顯,加密應(yīng)該用到這兩個(gè)字段,奇怪的是這兩個(gè)字段沒有初始值,應(yīng)該是IL2CppDumper沒分析出來,因?yàn)橛?cctor類型初始化器的話,應(yīng)該至少有一個(gè)字段是有初始值的,不然應(yīng)該不會(huì)存在。
那只能繼續(xù)用IDA分析了。

進(jìn)到IDA后直接跳到0x1819A4F90處查看類型初始化器。

稍微做了一下備注(備注的有點(diǎn)不對),
其中
對應(yīng)的是變量 pw
對應(yīng)的是變量 salt
而圖中的 pw, salt 其實(shí)是這兩個(gè)變量的初始值的地址。
然后在stringliteral.json中搜索 pw和salt 對應(yīng)的地址偏移




得到了兩個(gè)字符串,
接下來就是分析解密方法,

該類重載了兩個(gè)Crypt方法,
一個(gè)參數(shù)是字符串類型,返回字符串類型,
另一個(gè)參數(shù)是字節(jié)數(shù)組,返回也是字節(jié)數(shù)組。
????也就是說理論上來講,游戲應(yīng)該存在兩種形式的加密類型數(shù)據(jù),一種是二進(jìn)制文件,一種是字符串型的加密。而字符串類型應(yīng)該都是base64的形式。
該游戲恰巧存在這兩種類型的文件。
首先分析一下,參數(shù)是string的Decrypt。

一些重要方法都已經(jīng)將名字改回來了,
前面一大堆都是一些尋址初始化啥的(猜的,反正不影響),
這一塊可以看到,輸入的字符串經(jīng)過FromBase64String后返回了字節(jié)數(shù)組,其實(shí)一般也就是這樣,字符串基本都是經(jīng)過base64的。
然后data之后輸入到Decrypt_byte這個(gè)方法里,
之后返回值又經(jīng)過get_UTF8的解碼,
之后一大堆已經(jīng)沒有意義了,基本可以確定是返回了一串字符串。
在這一過程中,最重要的環(huán)節(jié)就是Decrypt_byte 這個(gè)方法。
Decrypt_byte 為了便于查看自己改了一下名字,其實(shí)就是另一個(gè)的輸入為byte[] 的Decrypt。
顯然解密的關(guān)鍵最終其實(shí)就是byte[] Decrypt(byte[] encrypted)

接下來查看該方法



????從中可以看出,用了AES加密,然后KEY是128位(16字節(jié)),IV也是128位(16字節(jié)) 模式是CBC,?末尾補(bǔ)齊是PKCS7。
然后是KEY和IV的生成,可以看到用的是Rfc2898DeriveBytes這個(gè)類(即PBKDF2)
????主要是輸入兩個(gè)字符串,作為密鑰和鹽進(jìn)行循環(huán)x次某種計(jì)算獲得一串hash值。Hash值中截取一部分就可以作為AES加密用的KEY和IV了,
????從上面的偽代碼中看出,所有的參數(shù)基本都是默認(rèn)的,甚至是代碼都可能是照著網(wǎng)上一些固定模板抄的,用到的字符串也是之前獲得的兩個(gè)字符串也就是說自己寫個(gè)C#腳本,就能解密了。
附上C#代碼:( pwd, salt )請自行查找
以及python版本: