1. 程式人生 > >Unity3d 加密 Assembly-CSharp.dll (Android平臺) 全記錄

Unity3d 加密 Assembly-CSharp.dll (Android平臺) 全記錄


0、加密的原理

Unity3d 是基於 Mono的,我們平時寫的 C# 指令碼都被編譯到了 Assembly-CSharp.dll ,然後 再由 Mono 來載入、解析、然後執行。

Mono 載入 Assembly-CSharp.dll 的時候就是讀取檔案到記憶體中,和平時讀取一個 遊戲資源 檔案沒什麼區別。

為了防止別人破解,我們會對遊戲資源加密,簡單點的 比如修改檔案的一個位元組 或者 位移一下 。只要簡單的修改一下,破壞原來的檔案資料結構,別人就不能用通用的讀取工具來讀取了。

Mono 讀取 Assembly-CSharp.dll 也是如此,我們只要簡單的 修改 Assembly-CSharp.dll 的一個位元組,就能破壞掉 Assembly-CSharp.dll 的資料結構,然後 Assembly-CSharp.dll 就不再是一個 dll 了,就變成了一個普通的檔案,一個系統都不認識的未知型別的檔案。

轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


在 Android 中,由 libmono.so 來載入 Assembly-CSharp.dll 。

libmono.so  這就是 Mono 了 。


既然 Assembly-CSharp.dll 被我們加密了,那 libmono.so 這個通用的讀取工具就不能再 讀取已經加密的 Assembly-CSharp.dll 了,所以我們也要修改 重新編譯 libmono.so ,給它加上解密函式才行。

Unity3d 是基於 Mono2.0 的,而 Mono2.0是免費開源的。所以基於各種開源協議 ,Unity 官方也將自己修改過的 Mono 開源出來,我們下載過來然後修改 重新編譯出自己的 libmono.so 。

專案託管在 Github 上,專案地址:

https://github.com/Unity-Technologies/mono

瞭解到一些原理背景後就可以開始進行操作了。

1、安裝ubuntu系統


在 Windows 上面進行編譯比較麻煩……在 Linux 或 Mac 上會比較簡單,網上多數教程都是基於 Mac的,我這裡選擇了最新的 Ubuntu 系統。

Ubuntu 官方提供了 ISO 燒錄工具:

http://www.pendrivelinux.com/downloads/Universal-USB-Installer/Universal-USB-Installer-1.9.6.3.exe 

Ubuntu 系統下載:

http://www.ubuntu.org.cn/download/desktop


http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04.1-desktop-i386.iso?_ga=1.187436840.1241524278.1457318071

轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

使用上面那個工具安裝到U 盤然後安裝到 電腦中。

2、下載ANDROID_NDK

安裝完 Ubuntu 後,在 Ubuntu 中   ,注意32 和64位區別

64 位下載 :

http://pan.baidu.com/s/1dDAqnK1
 

32位下載  :

http://pan.baidu.com/s/1sjoneRr 


sudo su 切換到root安裝

./android-ndk-r10e-linux-x86.bin

安裝後在安裝目錄裡面找到 RELEASE.txt ,裡面記錄著NDK 完整版本號,修改為 r10e

(Mono的編譯指令碼是讀取這個RELEASE.txt中記錄的版本號,然後和編譯指令碼中填寫的版本號做匹配的,如果不匹配就會去Google下載)

設定環境變數 ANDROID_NDK_ROOT
sudo gedit /etc/bashrc

新增一行

export ANDROID_NDK_ROOT=/home/captain/Downloads/android-ndk-r10e;


讓環境變數立即生效
source /etc/bashrc


測試是否新增成功
echo $ANDROID_NDK_ROOT


3、編譯 Development 版本的 libmono.so

從 Github 下載 unity-mono,我這裡下載的4.6版本,到branch裡面搜4.6

https://github.com/Unity-Technologies/mono/tree/unity-4.6

解壓,然後拷貝 mono-unity-4.6/external/buildscript/build_runtime_android.sh 到   mono-unity-4.6/   根目錄中。

切換到mono-unity-4.6/ 目錄中,使用 root 執行 build_runtime_android.sh ,
./build_runtime_android.sh
轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

會提示沒有安裝git

然後安裝git:

sudo apt-get install git

修改 build_runtime_android.sh Line 113 ,改為:
(cd "$KRAIT_PATCH_PATH" && perl ./build.pl)

然後修改 mono-unity-4.6/external/android_krait_signal_handler/build.pl

(這是指令碼呼叫git clone過來的 https://github.com/Unity-Technologies/krait-signal-handler/)

刪掉第一行

#!/usr/bin/env perl -w


繼續執行出錯,提示 ANDROID_NDK 版本不對,又要下載,下載又失敗,修改成我們自己的版本。

用命令  找到build.pl
Find / -name "build.pl"

修改BuildAndroid 函式裡面的 r9 為 自己下載的版本  r10e

然後找到

external/android_krait_signal_handler/jni/Application.mk 


修改裡面的

 TOOLCHAIN_VERSION := clang3.3


 TOOLCHAIN_VERSION :=4.8

因為r10e裡面已經沒有3.3了,只有4.8。

轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

然後繼續編譯

提示沒有 autoreconf

使用下面命令安裝autoreconf:

sudo apt-get update
sudo apt-get install autoconf


同樣的方法,順便把下面的包都安裝一下
* autoconf
* automake
* bison
* gcc
* gettext
* glib >= 2.0
* libtool
* make
* perl



都安裝之後,繼續執行指令碼,開始編譯滾程式碼了

過了十多分鐘,編譯好啦,用 find / -name "libmono.so" 找到編譯出來的 so 檔案。

這次編譯出來的是 Development 版本的,現在就可以 把這個 編譯出來的 libmono.so 拷貝到 自己電腦上,在匯出 Android 專案之後,替換掉 libs目錄裡面的 libmono.so 。

然後執行到 手機上測試是否OK,我這裡是測試 OK的。

至於怎麼樣從 Ubuntu 電腦上把 libmono.so 拷貝到 Windows 電腦上,直接用 U 盤就可以。然而我沒有 U盤,所以我在 Ubuntu 上開啟了 SSH 服務,然後在 Windows 上面連線到了 Ubuntu ,然後下載到 Windows 電腦上,比較麻煩。

轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

在Ubuntu上開啟ssh-server ,安裝完畢之後自動會啟動

apt-get install openssh-server

手動啟動服務
service ssh start
/etc/init.d/ssh start

檢視是否啟動成功
ps -s | grep ssh


在windows上安裝 FileZilla 官網 https://filezilla-project.org/
http://jaist.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.16.0/FileZilla_3.16.0_win64-setup_bundled.exe

輸入Ubuntu的 ip 帳號 密碼 埠22 進行SFTP連線 。

4、編譯 Release 版本的 libmono.so

修改所有的 build_runtime_android.sh 和 build_runtime_android_x86.sh

找到 -fpic -g 去掉 -g

再次執行 build_runtime_android.sh

開始編譯滾程式碼了,

編譯成功,用 find / -name "libmono.so" 找到編譯出來的 so 檔案。然後同樣 拷貝到 Windows 電腦上,匯出一個 Release 版本的 Android 工程出來,執行到手機上測試。

我這邊測試OK。

5、修改 libmono.so ,增加 解密 函式

找到 /metadata/image.c 這個檔案

找到

mono_image_open_from_data_with_name

這個函式,這個函式就是用來讀取 dll 的。修改這個函式,新增解密程式碼。

mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name)
{
    MonoCLIImageInfo *iinfo;
    MonoImage *image;
    char *datac;
    
    /* 加入 Decrypt */
    if(name != NULL)
    {
        if(strstr(name,"Assembly-CSharp.dll")){
            data[0]-=1; //這裡注意對應自己的加密方式進行修改。這裡是對第一個位元組 -1 ,對應加密演算法是 +1;
        }
    }
	
	………………
	………………
}

這裡注意對應自己的加密方式進行修改。這裡是對第一個位元組 -1 ,對應加密演算法是 +1;
轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
再次執行 build_runtime_android.sh

開始編譯滾程式碼了,

編譯成功,用 find / -name "libmono.so" 找到編譯出來的 so 檔案。拷貝到Windows 電腦上。

再次匯出一個 Release 版本的 工程,然後執行到 手機上發現,場景正常,但是程式碼都不執行了!!

這是因為 我們修改了 libmono.so ,增加了解密函式,但是當前的 Assembly-CSharp.dll 是沒有加密的!!!,所以 libmono.so 這裡是讀取 Assembly-CSharp.dll 失敗了,所以我們寫的程式碼都沒有執行。

現在已經知道了怎麼增加解密方法,以及編譯 Development 和 Release 版本。

所以現在分別編譯 Development 、 Release 的加密了的 libmono.so 。

每次編譯 都會自動生成  armv7a 、 x86  這兩個 CPU 的 libmono.so 。

我們把 這幾個 libmono.so 拷貝到 Unity 專案中,存放到 Editor 資料夾,可以下載我的例子檢視。

6、加密 Assembly-CSharp.dll

在 Unity3d 中匯出 Android 工程之後,對 Assembly-CSharp.dll 進行加密,然後替換掉 匯出的 Android 工程中的 libmono.so 檔案。

Unity3d 提供了 Android 工程匯出完畢的回撥,我們在這個回撥中 替換掉 匯出的 Android 工程中的 libmono.so 檔案, 如下:

BuildPostprocessor.cs :

/**
 * 檔名:BuildPostprocessor.cs
 * Des:在匯出Eclipse工程之後對assets/bin/Data/Managed/Assembly-CSharp.dll進行加密
 * Author:Captain
 * **/


using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.IO;

public class BuildPostprocessor
{
    [PostProcessBuildAttribute(1)]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
    {
        if (target == BuildTarget.Android && (!pathToBuiltProject.EndsWith(".apk")))
        {
            Debug.Log("target: " + target.ToString());
            Debug.Log("pathToBuiltProject: " + pathToBuiltProject);
            Debug.Log("productName: " + PlayerSettings.productName);

            string dllPath = pathToBuiltProject + "/" + PlayerSettings.productName + "/" + "assets/bin/Data/Managed/Assembly-CSharp.dll";

            if (File.Exists(dllPath))
            {
                //加密 Assembly-CSharp.dll;
                Debug.Log("Encrypt assets/bin/Data/Managed/Assembly-CSharp.dll Start");

                byte[] bytes = File.ReadAllBytes(dllPath);
                bytes[0] += 1;
                File.WriteAllBytes(dllPath, bytes);

                Debug.Log("Encrypt assets/bin/Data/Managed/Assembly-CSharp.dll Success");

                Debug.Log("Encrypt libmono.so Start !!");

                Debug.Log("Current is : " + EditorUserBuildSettings.development.ToString());

                //替換 libmono.so;
                if (EditorUserBuildSettings.development)
                {
                    string armv7a_so_path = pathToBuiltProject + "/" + PlayerSettings.productName + "/" + "libs/armeabi-v7a/libmono.so";
                    File.Copy(Application.dataPath + "/MonoEncrypt/Editor/libs/development/armeabi-v7a/libmono.so", armv7a_so_path, true);

                    string x86_so_path = pathToBuiltProject + "/" + PlayerSettings.productName + "/" + "libs/x86/libmono.so";
                    File.Copy(Application.dataPath + "/MonoEncrypt/Editor/libs/development/x86/libmono.so", x86_so_path, true);
                }
                else
                {
                    string armv7a_so_path = pathToBuiltProject + "/" + PlayerSettings.productName + "/" + "libs/armeabi-v7a/libmono.so";
                    File.Copy(Application.dataPath + "/MonoEncrypt/Editor/libs/release/armeabi-v7a/libmono.so", armv7a_so_path, true);

                    string x86_so_path = pathToBuiltProject + "/" + PlayerSettings.productName + "/" + "libs/x86/libmono.so";
                    File.Copy(Application.dataPath + "/MonoEncrypt/Editor/libs/release/x86/libmono.so", x86_so_path, true);
                }

                Debug.Log("Encrypt libmono.so Success !!");
            }
            else
            {
                Debug.LogError(dllPath+ "  Not Found!!");
            }
        }
    }
}

轉自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

好了,以上就是所有的 步驟。

再次匯出 Android 工程,然後執行到手機上,測試是否OK,我這邊是測試 OK的。

然後找到 匯出的專案中的 dll 檔案,在下面的路徑:

assets/bin/Data/Managed/Assembly-CSharp.dll

用 .NetReflector 檢視、或者拖入到 MonoDeveloper 中,發現都無法正常開啟。

這說明我們加密成功了!!


可以下載我的測試專案來檢視和測試:

http://pan.baidu.com/s/1nuloVcH

我也把它打包成了 Package:
http://pan.baidu.com/s/1o6ZH02u

注意這裡只是簡單加密,線上專案不要搞的這麼簡單…………

參考了網上各種教程:

http://csftech.logdown.com/posts/452269-android-unity-encryption

https://github.com/Unity-Technologies/mono

http://www.luzexi.com/unity3d/%E6%B8%B8%E6%88%8F%E6%9E%B6%E6%9E%84/%E5%89%8D%E7%AB%AF%E6%8A%80%E6%9C%AF/2015/04/11/Unity3D-%E9%87%8D%E6%96%B0%E7%BC%96%E8%AF%91Mono%E5%8A%A0%E5%AF%86DLL.html

http://www.xuanyusong.com/archives/3553


相關推薦

Unity3d 加密 Assembly-CSharp dll Android平臺 記錄

                0、加密的原理Unity3d 是基於 Mono的,我們平時寫的 C# 指令碼都被編譯到了 Assembly-CSharp.dll ,然後 再由 Mono 來載入、解析、然後執行。Mono 載入 Assembly-CSharp.dll 的時候就是讀取檔案到記憶體中,和平時讀取一個

Unity3d 加密 Assembly-CSharp.dll (Android平臺) 記錄

0、加密的原理Unity3d 是基於 Mono的,我們平時寫的 C# 指令碼都被編譯到了 Assembly-CSharp.dll ,然後 再由 Mono 來載入、解析、然後執行。Mono 載入 Assembly-CSharp.dll 的時候就是讀取檔案到記憶體中,和平時讀取一

Unity3D 加密 Assembly-CSharp.dll (Android平臺) 防止反編譯

0、加密的原理 Unity3D 是基於 Mono的,我們平時寫的 C# 指令碼都被編譯到了 Assembly-CSharp.dll ,然後 再由 Mono 來載入、解析、然後執行。 Mono 載入 Assembly-CSharp.dll 的時候就是讀

Cross compilation job Assembly-CSharp.dll failed.UnityException: Failed AOT cross compiler

 Cross compilation job Assembly-CSharp.dll failed. UnityException: Failed AOT cross compiler 刪除所有cs檔案,然後慢慢恢復,看看恢復到哪個檔案出問題 另外“Script

我不斷地得到報告“Assembly-CSharp.dll.mdb”被拒絕訪問的訊息

症狀 我不斷地得到一個編譯錯誤,每當我在我的遊戲裡使用C#時。 原因 你正在windows機器上建立一個遊戲,並且當你嘗試編譯你的專案時總是收到如下內部編譯器錯誤: “Unhandled Exception: System.Unauthor

你想要的平臺棧開源專案 - Vue、React、小程式、Android原生、ReactNative、java後端

全平臺全棧開源專案 coderiver 今天終於開始前後端聯調了~ 首先感謝大家的支援,coderiver 在 GitHub 上開源兩週,獲得了 54 個 Star,9 個 Fork,5 個 Watch。 這些鼓勵和認可也更加堅定了我繼續寫下去的決心~ 再次感謝各位大佬! 專案地址: github.co

android 平臺NDK MD5加密

char* szText = (char*)(*env)->GetStringUTFChars(env, strText, 0); MD5_CTX context = { 0 }; MD5Init(&context); MD5Update(&c

Android平臺 AES加密/解密

網上有些程式碼在執行解密時丟擲錯誤:javax.crypto.BadPaddingException: pad block corrupted  以下程式碼親測執行無誤: package com.example.testandroid; import java.secu

記錄U3D逆向Assembly-CSharp-firstpass.dll解密

原創:狂神說  ----未經授權禁止止轉載----- 一個愛鑽研程式碼的低端碼農!學習了這麼久,以後工作開始不定時分享給大家經驗~ 最近一直想逆向一個自己一直在玩的手遊 就把其中遇到的一些問題記錄下來分享給大家吧 使用到的工具 APKIDE .NET Reflec

Android平臺的 Ptrace, 注入, Hook 攻略

Android平臺上的Ptrace已經流行很久了,我記得最早的時候是LBE開始使用Ptrace在Android上做攔截,大概三年前我原來的同事yuki (看雪上的古河) 寫了一個利用Ptrace注入的例子,被廣泛使用,聽說他還因此當上了版主,呵呵:Android平臺上的注

kotlin, 一種新的android平臺一級開發語言

程序 16px 語法 jvm ava lin 使用 ide 擁有 最近看到一則科技新聞, 大致內容是google將kotlin語言作為android應用開發的一級語言, 與java並駕齊驅, 這是一個開發界的大事件大新聞, 連google的親兒子go語言也沒有這

Cocos2d-x v3.0正式版嘗鮮體驗【2】 Android平臺移植

生成 ble ack nts 做的 導入 eclipse so文件 腳本 今天沒事又嘗試了下3.0正式版關於Android平臺的移植,把新建的項目移植了下。過程僅用了十分鐘左右,什麽概念?!好吧,事實上我想說,這個版本號真的移植非常輕松啊,只是還沒加上其它東西,只是就眼

android平臺打印C語言日誌

as2 使用 pri 2.0 tag bug logs .com 3-9 在android平臺打印C語言日誌 1、操作平臺:AS2.0 2、步驟如下: 在C代碼中添加如下代碼: #define LOG_TAG "我的C語言日誌:" #define LOGD(...) _

Android平臺Camera實時濾鏡實現方法探討(十一)--實時美顏濾鏡

.net 兩個 其它 強人 突出 pad eight 地址 模式 上一章完畢了對圖片的磨皮處理。經過簡單算法流程優化,能夠達到非常快的速度。可是不能用於實時美顏。經實驗,若採用僅僅處理Y信號的方案。半徑極限大約是5-10,超過10則明顯感受到卡頓。但對於1920X1

Android平臺錄音音量計的實現

type 源代碼 cti ddc res javascrip his 顯示 中間 今天博主要給大家分享的是怎樣在Android平臺上實現錄音時的音量指示計。開門見山。先來看一張Demo的效果圖: 如上圖所看到的,兩個button各自是開始錄音和停止

unity3d動態加載dll的API以及限制

軟件 ddc line tel 同時 eat 都是 version tails Unity3D的坑系列:動態加載dll 一、使用限制 現在參與的項目是做MMO手遊,目標平臺是Android和iOS,iOS平臺不能動態加載dll(什麽原因找喬布斯去),可以直接忽略,而在

Android平臺Camera實時濾鏡實現方法探討(十)--代碼地址以及簡單介紹(20160118更新)

div iss 將在 spa 方法 target 用途 net dsm 簡單做了個相機和圖片編輯模塊,時間原因非常多功能還沒有做。尚有BUG,見諒,將在以後抽時間改動 代碼地址 PS:請點個Star^-^ -----------------------

aNDROID平臺應用軟體開發

平臺 lis oid andro music 5% baidu .com aid aNDROID%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%E5%9B%9E%E8%B0%83%E6%9C%BA%E5%88%B6 http://music.hao

Android視頻播放方案選擇——深刻分析android平臺的視頻播放優缺點

位置 player 帶來 epg 代理服 reset 如何 rac 下一個 https://zhuanlan.zhihu.com/p/27029577?utm_source=qq&utm_medium=social Android我還可以相信你多少系列文章二之

Android平臺調用Web Service:線程返回值

繼承 write 能夠 call() ted uil code 等待 @override 接上文 前文中的遺留問題 對於Java多線程的理解。我曾經只局限於實現Runnable接口或者繼承Thread類,然後重寫run()方法,最後start()調用就算完事。可