Hello,我是KitStar。
以下文章整理的不對。還請見諒。
詳細介紹U3D項目加密解密方式??梢员WC的說,只要你認真看完??隙ň蜁晒?。(畢竟這是我在坑里滾出來的經(jīng)驗
對付反編譯,比較成熟的方案無非就兩種,一種是加密(加殼),一種是混淆(詳細鏈接)。前一種方案,就是對U3D編譯出來的dll文件進行二次加密。后一種,就是把程序的可讀性,降低到令人發(fā)指的程度。當黑客拿到源代碼后,也是氣血上涌,眼前發(fā)黑。好的混淆,需要花極大的精力,才能還原。當他攻破的時候,我們改改程序再混淆,重新發(fā)布就又夠他折騰的了。 Unity C#代碼部分的加密,很多人說混淆,雖然有幾個混淆插件CodeGuard、CryptoObfuscator、de4dot...可以用用,但有混淆就有反混淆(de4dot基本都可以搞定),有加殼就有脫殼,有加密就有解密...加密只是提高了門檻提高了難度,而解密只是時間的長短而已。
編譯自己的Unity項目,找到 /Data/Managed/Assembly-CSharp.dll ,對它進行加密,可以自己寫個小程序,把Assembly-CSharp.dll轉(zhuǎn)換成字節(jié)流byte[],然后對byte[]加密。
下面是一些常用的加密(效驗)算法:
* 散列:MD5、SHA、SHA3、RIPEMD、Tiger、Whirlpool、CRC32、Adler32
* 對稱:Base64、DES、3DES、AES、RC、Rijndael、TripleDES、PBE、3-way、IDEA、MARS、Serpent、 SAFER、 Blowfish、Twofish、Tea、Skipjack、Camellia、Cast、Gost
* 非對稱:RSA、Elgamal、Diffie-Hellman、Rabin、ECDsa、Ecc
若對以上算法不了解的可以參看下面兩個開源加密類庫(谷歌度娘也可以的)
Bouncy Castle(C#和Java版) 代碼下載:https://github.com/bcgit/ 官網(wǎng)地址:http://www.bouncycastle.org
Crypto++(C++版) 代碼下載:http://sourceforge.net/projects/cryptopp/files/cryptopp/ 官網(wǎng)地址:http://www.cryptopp.com/
安卓端:Unity3D基本客戶端的多數(shù)代碼都會以dll文件形式存下來,功能都在Assembly-CSharp.dll文件中。
當游戲應(yīng)用被開啟時c#vm(也就是mono的虛擬機)會去加載所有dll,從而開始運行真正的程序畫面了。而破解的很大一部分都是通過解壓apk后拿到主邏輯dll,對dll進行反編譯,然后修改后重新編譯,再放入apk重新簽名打包。所以我們需要針對dll進行加密,以防止他們反編譯dll(反編譯工具鏈接:Reflector9VSPro,已經(jīng)破解)。
加密一個dll文件非常容易,無論你用什么算法都行,但是在哪解密呢?答案是libmono.so。
libmono.so是mono的核心程序,它承載了加載解析dll和虛擬機運行的功能。所以說libmono.so是關(guān)鍵,我們需要修改mono內(nèi)核程序并重新編譯它。
PC端:Pc端與安卓同理,只是不同文件。用于PC加載解析dll和虛擬機運行的文件是在程序打包之后下Mono文件夾的mono.dll文件。所以Pc中mono.dll是關(guān)鍵。我們需要修改mono內(nèi)核程序并重新編譯一個mono.dll. 而在這個dll中將存在這解密Assembly-CSharp.dll文件的代碼。
那么下來說到底怎么加密解密嘍?。。。。。。。。?!
PC端加密解密步驟:
一,加密Assembly-CSharp.dll。
在閱讀這篇文章之前,我在處理mono加密問題時,也是參考了雨凇的文章,所以建議先看一下雨凇寫的關(guān)于加密Dll的文章:
1.Unity3D研究院之Android加密DLL與破解DLL .SO
2.Unity3D研究院之Android二次加密.so二次加密DLL
假裝讀者已經(jīng)看過上面的兩篇文章了,下面我會記錄一下我做的整個加密流程。
我們主要目的是對程序集:Assembly-CSharp.dll 進行加密,然后修改mono源碼,在mono加載Dll的時候進行解密。顯然我們需要一種可逆、對稱的加密算法,其實這類算法很多,如DES、TEA、XXTEA等,一般這類對稱秘鑰算法的安全性都是基于秘鑰的(Key),所以如何在mono解密是保護自己的秘鑰就十分重要了。我目前使用的是XXTEA,實現(xiàn)的話不清楚,但是github上有開源實現(xiàn),所以直接拿來用了:xxtea-c
1.先用Unity導出一個PC工程,在工程路徑 xxxxx\xxxx_Data\Managed\Assembly-CSharp.dll ,這個文件就是需要我們替換的程序集啦.找到之后,等待備用。
2.編寫加密Dll工具,大家可以把上面開源xxtea項目中的源碼:xxtea.h、xxtea.c 和下面自己要寫的的encryptDll.c代碼放在同一目錄,用MinGW(相關(guān)鏈接)下的gcc編譯就可以了:gcc xxtea.c encryptDll.c –o EncryptDll
encryptDll.c代碼如下:
此時,再把你需要加密的Assembly-CSharp文件放到這個文件夾中。最后,直接點擊EncryptDll.exe進行對Assembly-CSharp.dll的加密。之后會生成一個加密后的Assembly-CSharp_encrypt.dll文件。此時把這個文件更名為Assembly-CSharp.dll。放回你的原來的打包好的了原文件中,進行替換。
此時,PC端Assembly-CSharp.dll的加密完成。
但是這帶來一個問題是,Unity不認加密后的DLL,因為它不再是dll格式了。那我們就需要修改Unity底層代碼,好在Unity是基于Mono的,而Mono是開源的。只要找到Mono重新編譯個帶有解密的mono.dll就可以。那么,下來開始進行mono.dll解密方法植入操作。
二,使用mono.dll進行對Assembly-CSharp.dll的解密。
注意:由于筆者在編譯的時候碰到各種坑。最后總結(jié)下來最好用VS2010進行編譯mono,反正用vs2015是各種坑。
Unity是基于Mono的,地球人都知道...它是開源的 代碼下載:https://github.com/Unity-Technologies/mono
直接下Zip包(注意Tag版本與開發(fā)用的Unity版本要相同)此處我用的是4.6的版本。
我們下載好了mono包之后。開始用這個包重新編寫一個自己的帶有解密方法的mono.dll文件。
1,使用上面下載的加密文件xxtea.c和xxtea.h復制到下載的mono的源碼里,具體位置在mono/mono/metadata文件夾下。
然后再用vs2010打開mono/msvc/mono.sln,打開之后,通過“解決方案資源管理器”找到libmono項,再將上面的xxtea的兩個文件添加到libmono里,并找到libmono下的image.c,添加頭文件#include "xxtea.h"和
#include <stddef.h>。
2,再到image.c文件中找一個方法:mono_image_open_from_data_with_name。這個函數(shù)就是mono去加載Assembly-CSharp.dll的入口,也就是說我們需要在這里添加我們說需要的解密函數(shù)。
第一個方法mono_image_open_from_data_full內(nèi)實際調(diào)用了mono_image_open_from_data_with_name
第二個方法mono_image_open_from_data_with_name的第一個參數(shù)char *data這個指針指向運行時Assembly-CSharp.dll的內(nèi)存地址,
可在該方法內(nèi)添加或調(diào)用對data解密的算法,然后將解密后的data再賦給datac
關(guān)于MonoImage這個結(jié)構(gòu)體,它的定義是typedef struct _MonoImage MonoImage; 而_MonoImage這個結(jié)構(gòu)體,它的定義在 /mono/metadata/metadata-internals.h 中
最后就是編譯Mono了,編譯部分我就不說了自行參看官方說明
該方法雖然是修改Mono內(nèi)核,偏底層了些,但并不是破解不了,只是要比反混淆的難度高那么一丟丟..
因為這里是針對unity的程序加密,我們完全可以針對單個名稱來找到dll。此時在此方法中添加解密代碼,如下:
a、打開Visual Studio Command Prompt(2010)
b、進入mono-unity-4.5\msvc目錄
c、執(zhí)行msbuild.exe mono.sln /p:Configuration=Release_eglib
注意:直接打開mono.sln解決方案,在Visual Studio底下是編譯不了的。
我這里用了54秒就編譯成功,生成的dll位置在mono\builds\embedruntimes\win64,同時建議在編譯的時候,最好將32與64位的dll文件,你后面多半都會使用到的。
最后把你編譯出來的mono.dll復制到你打包出來的項目中的Mono文件夾中進行替換。
好了,OK。你可以試試運行游戲,完美運行。再用反編譯工具去編譯Assembly-CSharp.dll。發(fā)現(xiàn)無法編譯。
目前測試中:可以成功編譯的由,unity-mono-4.6。unity-mono-5.1。unity-mono-5.5.
安卓端加密解密步驟:
請看下一篇更加詳細的文章:
source ~/.bashrc
source ~/.bashrc
使用APKTool從新打包APK相關(guān)命令:
1, apktool d unity5.6.apk
2,apktool b unity5.6 -o newtest.apk
3,jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore likai.keystore -storepass 此處為密碼 newtest.apk likai