安卓U3D逆向從Assembly-CSharp到il2cpp

隨著unity技術(shù)的發(fā)展及廠商對(duì)于腳本源碼的保護(hù),很大一部分U3D應(yīng)用的scripting backend已經(jīng)由mono轉(zhuǎn)為了il2cpp,本文從unity簡(jiǎn)單應(yīng)用的制作講起,介紹U3D應(yīng)用腳本的Assembly-CSharp.dll的逆向及il2cpp.so的逆向分析。


目錄如下:

0x1.U3D應(yīng)用制作  →  輸出兩個(gè)apk,分別為mono和il2cpp

0x2.mono后臺(tái)apk的逆向分析  →  Assembly-CSharp.dll 逆向修改

0x3.il2cpp后臺(tái)apk的逆向分析  →  il2cpp.so逆向修改


正文內(nèi)容:

0x1.U3D應(yīng)用制作

工具:Unity最新版本 2017.2.1f1

1.1  創(chuàng)建Project

新建一個(gè)Unity3D Project,Project name為UnityTest,如下圖



1.2  創(chuàng)建script定義界面元素

創(chuàng)建GameObject和C# Script,均命名為Sample, 同時(shí)創(chuàng)建兩個(gè)UI Text,分別命名為HP和Attack。打開C# Script,進(jìn)行界面元素的義,創(chuàng)建三個(gè)矩形按鈕分別為HP,ATK和LevelUP,設(shè)置點(diǎn)擊HP顯示100,點(diǎn)擊ATK顯示50,點(diǎn)擊LevelUP后HP和ATK的值都翻倍。

using UnityEngine;
using UnityEngine.UI;
public  class  Sample : MonoBehaviour
{
         public Text _hp;
         public Text _attack;
 
         private Rect _healRect  =  new Rect( 10f ,  20f ,  300f ,  100f );
         private Rect _attackRect  =  new Rect( 10f ,  170f ,  300f ,  100f );
         private Rect _LevelUpRect  =  new Rect( 10f ,  320f ,  300f ,  100f );
 
         public void SetHp( int  hp)
     {
         _hp.text  =  hp.ToString();
     }
 
     public void SetAttack( int  attack)
     {
         _attack.text  =  attack.ToString();
     }
 
     public void OnGUI()
     {
         int  hp_value  =  100 ;
         int  attack_value  =  50 ;
         if  (GUI.Button(_healRect,  "HP" ))
             {
                 SetHp(hp_value);
             }
         if  (GUI.Button(_attackRect,  "ATK" ))
             {
                 SetAttack(attack_value);
             }
         if  (GUI.Button(_LevelUpRect,  "LevelUp" ))
             {
                 SetHp(hp_value  *  2 );
                 SetAttack(attack_value  *  2 );
             }
         }
}

代碼和界面完成后,我們?cè)O(shè)置包名(com.test.test)進(jìn)行打包,分別輸出mono后臺(tái)和il2cpp后臺(tái)的apk。

點(diǎn)擊Player Setting進(jìn)行后臺(tái)設(shè)置,可點(diǎn)擊Scripting Backend選擇mono或者il2cpp。

得到的apk我們分別命名為Sample-mono.apk和Sample-il2cpp.apk。

安裝測(cè)試正常,界面如下:

初始界面

點(diǎn)擊HP和ATK后界面

點(diǎn)擊LevelUp后界面

至此,我們完成了兩種后臺(tái)的apk的創(chuàng)建,接下來先對(duì)mono后臺(tái)的apk進(jìn)行逆向分析。


0x2.mono后臺(tái)apk的逆向分析


工具:Android Killer,DnSpy

思路:將Sample-il2cpp.apk拖拽進(jìn)Android Killer進(jìn)行反編譯,獲取到腳本文件/Assets/bin/Data/Managed/Assembly-CSharp.dll,dll拖進(jìn)DnSpy進(jìn)行反編譯分析,修改關(guān)鍵method后,保存并重新打包運(yùn)行。

Android Killer部分不再上圖,Assembly-CSharp.dll拖拽進(jìn)DnSpy,我們可以很輕易的找到我們需要的關(guān)鍵函數(shù),如圖:

根據(jù)代碼信息,我們可以確定,num為初始HP,num2為初始ATK,我們?cè)诖送ㄟ^編輯IL指令將他們的值分別改為1000和500,如圖:

確認(rèn)后C#編碼變更如下:

保存后,重新打包apk安裝測(cè)試結(jié)果如下:

至此,我們的mono后臺(tái)apk修改已經(jīng)完成,接下來我們進(jìn)行il2cpp后臺(tái)apk的修改。


0x3.il2cpp后臺(tái)apk的逆向分析

工具:Android Killer,il2cppDumper,IDA,010Editor

思路:利用il2cppDumper獲取到關(guān)鍵函數(shù)的offset后,使用IDA找到關(guān)鍵函數(shù),分析匯編語言邏輯后,利用010Editor進(jìn)行16進(jìn)制文件編輯來實(shí)現(xiàn)修改。

Android Killer相關(guān)操作再次不做贅述,反編譯后我們得到的Project中,lib目錄如圖:

在此我們只分析armeabi-v7a文件夾下的libil2cpp.so,x86為intel架構(gòu),暫不做分析處理。

將il2cpp.so連同assets\bin\Data\Managed\Metadata 目錄下的global-metadata.dat 文件一起放進(jìn)il2cppDumper目錄。


運(yùn)行il2cppDumper,第一步,選擇il2cpp.so


第二步,選擇global-metadata.dat

進(jìn)入到il2cppDumper控制臺(tái)界面


選擇mode后可以得到Dump.cs,包含關(guān)鍵函數(shù)的偏移信息


打開Dump.cs,找到關(guān)鍵函數(shù)的偏移信息


用IDA打開libil2cpp.so文件,跳轉(zhuǎn)到此偏移地址 0x7CE514


定位到關(guān)鍵函數(shù)后,我們可以看匯編,也可以F5插件看偽代碼,為了便于理解我們這里F5處理一下

這次我們從LevelUp入手,我們?cè)诰帉懺创a的時(shí)候,是進(jìn)行了乘以2的處理,為什么匯編語言中是直接將翻倍后的數(shù)值進(jìn)行傳參呢,因?yàn)閰R編不會(huì)完全跟我們?cè)创a的邏輯相同,但是結(jié)果一定是一樣的,LevelUp的匯編代碼如下

切換到對(duì)應(yīng)的地址查看16進(jìn)制

0xC8即為200,我們使用010Editor將其地址7CE6B4的值修改為FF(十進(jìn)制為255)

保存后替換lib/armeabi-v7a目錄下的libil2cpp.so文件,打包運(yùn)行,結(jié)果如下

至此,il2cpp后臺(tái)的apk已修改完畢。

?