Unity4.x版本導出android包時,只能選擇mono,無法使用il2cpp,這就造成了我們的程序集很容易被修改……很多朋友在發布項目時覺得即使代碼暴露出去也沒什么關系,只有項目火了才有必要等,然而一旦游戲被破解,很容易對游戲生態造成無法想象的災難,這里寫兩篇博文記錄一下最近加密Dll的過程。
一.加密Dll需要做那些事
1. 想要加密Dll的前提條件是我們必須修改mono,因為Unity並沒有在mono中為開發者提供加密的接口或者功能,所以我們必須手動編譯mono,從而替換掉Unity中原本的mono。
2.需要一種加密Dll的可逆算法,常見的DES,TEA,XXTEA等,當然需要是C語言的實現
3.mono中對key的保護,因為即使.so文件,也是可以被反編譯的,如神器IDA等
4.一些打包工具或者腳本,因為一旦自己加密了Dll就無法完全依賴Unity打包了,整個打包流程會變得相對繁瑣,這事需要反復打包的話最好還是優化對應的工具。
這兩篇博文都是基於Untiy4.7版本的,對應的mono是4.6,當然我想如果是其他版本的mono應該也是可以的。
二.編譯mono
編譯mono的過程其實還是很繁瑣的,一開始我嘗試在linux下編譯mono,然而各種失敗,我想Unity可能並不想開發者自己編譯mono,所以給的文檔中各種坑,然后參考了雨凇編譯mono的文章,結果發現也是各種失敗,汗……后來意外發現在 “ulua&cstolua技術交流群①(341746602)”“不說害怕”大神寫過一篇編譯mono的教程,於是拿過來試了一下,踩了幾個小坑后就順利編譯成功了,下面就直接這篇簡單修改一下貼出來啦:
1.獲得Unity-mono
我們需要編譯的是 針對unity-4.6 mono的安卓SO,所以首先需要clone Unity-mono ,然后切到分支unity-4.6,(注意:已經測試編譯過unity-5.2,所以對於最新的版本應該也可以的)
2. 准備編譯環境
下載ulua編譯的那個MinGW(msys) 【注意:里面包含x86和x64我用的x86版本,但同時支持編譯出各個版本的結果】放到D:\MinGW\ 【注意MinGW一定要放在某個磁盤的根目錄,否則會造成MinGW環境變量錯誤,導致編譯失敗】
參考:
https://github.com/jarjin/ulua_runtime_project
http://pan.baidu.com/s/1gd1Wyx9#path=%252Fulua_src
3. 下載
首先需要下載NDK : android-ndk-r10e
==========================
注意至於是不是下載這個NDK版本,到\mono\external\build_runtime_android.sh這個文件
第14行確認:
例如這樣: perl ${BUILDSCRIPTSDIR}/PrepareAndroidSDK.pl -ndk=r10e -env=envsetup.sh && source envsetup.sh
>>>>>>>>>>>>>>>>>>>>>>>>>
上面下載的文件是一個.exe的文件,運行一下它就會在當前目錄解壓,解壓完成把目錄名改成 android-ndk_auto-r10e
放到
D:\MinGW\x86\msys\1.0\home\zhupf\android-ndk_auto-r10e 【zhupf 是我的windows登陸名字】
4. 下載一個zip.exe
zip.exe很多,這里直接在文章提供一個Zip, 下載並解壓后直接放到-> D:\MinGW\x86\msys\1.0\bin
5. 修改一行腳本
文件 E:\Work\mono\external\buildscripts\PrepareAndroidSDK.pm 需要處理一下:
elsif(lc $^O eq 'cygwin')
改成,不然不認識我們的編譯環境
elsif(lc $^O eq 'cygwin' or lc $^O eq 'msys')
5. 啟動
運行 D:\MinGW\x86\msys\1.0\msys.bat,切換到mono 工程目錄,如:E:\Work\mono\ ,然后執行編譯腳本:./external/buildscripts/build_runtime_android.sh
7. 第一次會失敗
自動用git下載android_krait_signal_handler但編譯可能失敗【需要把git加到環境變量中】
下載E:\Work\mono\external\android_krait_signal_handler
但編譯失敗
8. 修改android_krait_signal_handler下的腳本
1)--------------
PrepareAndroidSDK.pm 內
elsif(lc $^O eq 'cygwin')
改成,不然不認識我們的編譯環境
elsif(lc $^O eq 'cygwin' or lc $^O eq 'msys')
2)--------------
build.pl內
#!/usr/bin/env perl -w
改成
#!/usr/bin/perl -w
PrepareAndroidSDK::GetAndroidSDK(undef, undef, "r9");
改成
#PrepareAndroidSDK::GetAndroidSDK(undef, undef, "r9");
3)--------------
\jni\Application.mk
NDK_TOOLCHAIN_VERSION := clang3.3
改成
#NDK_TOOLCHAIN_VERSION := clang3.3
9. 重新編譯
./external/buildscripts/build_runtime_android.sh
10. 成功編譯到
E:\Work\mono\builds\embedruntimes\android
11. 注意
1)--------------
這樣會編譯出針對4種處理器的庫
armv5, armv6_vfp, armv7a, x86
可以根據情況修改(在這個文件最后,用#注釋掉不需要的)
E:\Work\mono\external\buildscripts\build_runtime_android.sh
以便精簡
比如:
#clean_build "$CCFLAGS_ARMv5_CPU" "$LDFLAGS_ARMv5" "$OUTDIR/armv5"
2)--------------
編譯出的so文件大約8m, 是Debug
若要編譯release版本
對於arm7等,修改build_runtime_android.sh
只要把CFLAGS里的-g改成-O2就可以了 【注意-O2 是gcc編譯優化選項,其中‘O’是英文字母'O’】
對於x86,修改build_runtime_android_x86.sh
去除CFLAGS里的-g
注:O是優化等級(Optimize)的參數
-g選項,表示產生供gdb調試的調試數據
參考:
http://www.xuanyusong.com/archives/3553
其中加-Wl,–gc-sections \ 這個我這邊試了會失敗,可以不加。
12. strip去除調試信息(可以加到build_runtime_android.sh和build_runtime_android_x86.sh腳本)
1)--------------
$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-strip.exe libmono.so
2)--------------
$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-strip.exe libmono.so
最后
下篇文章會介紹如何加密Dll和在mono中保護key的問題 : http://www.cnblogs.com/lixiang-share/p/5979981.html
