移動平台游戲框架主要有unity 3d和cocos 2d。我們首先得識別游戲使用的框架。
識別Unity游戲
Android平台的apk包可以直接解壓,看是否有./assets/bin/Data/Managed目錄,也可以查看lib文件夾下面包含的一些so,如果有libmono,libunity等模塊,基本可以確定是unity游戲了。
Android平台中C#編寫的主邏輯模塊代碼靜態編輯之后存儲於Assembly-CSharp.dll文件中。因為unity的跨平台,Android平台是unity編譯的游戲,那么其對應的IOS平台上也是unity編譯出來的。如果希望直接從IOS上面去看是否是unity游戲,可以提取游戲中的主模塊查看是否有unity之類的函數即可。
破解思路
下面列舉了一些破解版思路,如果能直接下斷點在函數頭修改寄存器可直接修改寄存器測試,遇到一些不能直接修改的,就用第二種方法,把修改后的Assembly-CSharp.dll注入到游戲中,讓游戲執行我們修改后的代碼。另外也可以動靜態修改二進制實現。
1、修改unity游戲邏輯代碼編譯成匯編代碼相關的值
(1) 修改傳進來的參數,即寄存器,一般是set之類的函數
(2) 匯編代碼中盡量不修改內存,不修改opcode,能改寄存器直接改寄存器
2、反編譯Assembly-CSharp.dll,直接修改unity的C#源代碼
(1) 修改函數返回值
(2) 直接刪除函數體,只剩下 ret 指令
(3) 在對應函數修改,對變量進行處理
(4) 在對應函數增加一些call處理,主動call
3、分析源碼直接修改代碼
(1) 通過分析unity反編譯后的源碼找到對應的匯編指令下斷點修改寄存器
(2) 通過直接靜態分析dll,直接修改IL碼的二進制碼
4、在加載dll的函數位置dump原來的dll代碼,可繞過dll加密,修改源代碼
hook住mono_image_open_from_data_full函數,dump出dll可以,用IDA配合jdb掛起進程在那函數位置下斷點dump也可以,源代碼具體修改方案同“2”和“3”
常用工具
1、IDA工具
可以進行動態調試和靜態分析的工具,能在合適的位置下斷點,修改指定寄存器和編寫IDC腳本配合分析
2、ILSpy
反編譯和分析dll代碼,可以交叉引用,可以以源碼形式保存反編譯的代碼,提供代碼給DirFind等字符串搜索定位工具定位代碼位置
3、.NET Reflector + Reflexil
反編譯和分析dll代碼,彌補了ILSpy一些功能性的缺陷,可以分析出錯誤的CLR文件頭,一些在ILSpy顯示不出的dll文件,如果只是因為dll頭部被修改,放在.NET Reflector中是可以分析出的。Reflexil則是.NET Reflector的一款插件,可以反編譯和回編譯IL碼,方便實用可視化。
4、Ilasm和ildasm
Ildasm可以反編譯dll,dump出反編譯后的il碼,而Ilasm則可以重打包il碼,利用命令ilasm /dll *.il即可。
常用IL碼二進制
(1)nop 二進制是 0x00
(2)ldc.i4.0 二進制是 0x16
(3)ldc.i4.1 二進制是 0x17
(4)ret 二進制是 0x2A
(5)ldc.r4 二進制是 0x22 ,后面跟四個字節
.NET Reflector + Reflexil的使用
用.NET Reflector打開Assembly-CSharp.dll,這里使用的.NET Reflector版本是9.0,Reflexil版本是2.1。如圖所示,通過這個Reflexil插件,我們可以插入字段、類、方法等。
通過Tools菜單下的Reflexil選項,可以打開unity代碼修改器:
在左邊單擊對應函數,就可以對該函數代碼進行修改了。
下面舉例分析。在逆向中我們經常需要插入log語句打印log信息來輔助分析。unity打印log的語句是:
Debug.Log 函數原型是:public static void Log(object message);
如果我們要打印下面函數中ToString的返回值應該如何操作呢?
按照正常邏輯,應該是先保存ToString()的值到寄存器,然后當作參數傳遞給Log函數打印出來。但是我不知道怎么保存這個值,所以想到了另外一個辦法,仿照原代碼,再次調用ToString()函數,然后將下面調用CalcMD5函數改為調用Debug.Log函數。
具體怎么操作呢?
(1)首先右擊“ldloc.3”那一行代碼(Offset為 196),選擇“Create new...”,OpCode選擇“ldloc.3”,然后點擊“Insert before select”。
stloc.1 將值從堆棧彈出到局部變量 1
ldloc.1 將索引 1 處的局部變量加載到計算堆棧上
(2)OpCode選擇“callvirt”,Operand type選擇“Method reference”,Operand選擇“ToString”函數(在mscorlib模塊找到System.Text.StringBuilder::ToString函數)。然后點擊“Insert before select”。
(3)OpCode選擇“call”,Operand type選擇“Method reference”,Operand選擇“Log”函數。這個函數是在UnityEngine中查找,如圖所示:
然后點擊“Insert before select”,如下圖所示:
添加代碼后的情況如下:
修改完成后,右鍵“Assembly-CSharp.dll”,依次點擊“Reflexil”,“Save as...”保存dll文件,重新打包安裝運行就可以看到log輸出信息了。