加密unity代码,防止反编译

Uinty3D打包应用之后总是让人头疼,所有的代码都会在/…_Data/Managed/Assembly-CSharp.dll文件中,而这个dll文件很容易被反编译,反编译之后自己辛苦的劳动成果被人随意窃取和利用,心里总归不舒服,所以我们需要加强自身的反破解能力,虽然这世上没有破解不了的东西,这里做的只是让破解的人付出点代价而已,最好是气血上涌,两眼发黑,然后砸电脑。

 

文章参考了大量的前人文章,在这里当作笔记记录下,希望能帮到同样想加密的小伙伴

参考文章1:https://blog.csdn.net/swj524152416/article/details/69946259

参考文章2:https://blog.csdn.net/a958832776/article/details/73548597

 

这里要加密程序代码就是不让电脑正常读取Assembly-CSharp.dll,电脑读取的文件是以字节流的形式存在于电脑中,所以加密只需要对这个文件的字节流加密,保存到Assembly-CSharp.dll文件中,不管使用什么方式加密,dll文件肯定有所变化,程序无法正常读取,也就是无法正常运行,Unity是基于开源的Mono,只需要在Mono读取的时候解密dll文件就行了,由于我们使用了加密的方式,所以必须在Mono里面添加一个解密步骤,再编译,替换掉之前没有解密步骤的mono,

1、加密流程就是:

  1. 准备好解密mono.dll
  2. 打包unity程序
  3. 加密Assembly-CSharp.dll
  4. 替换掉打包程序的mono.dll

 

2、Mono的下载和重编译

Mono源码下载链接:https://github.com/Unity-Technologies/mono

根据所使用的unity版本,下载相对应的Mono源码。

也可以滑到下方找对应的unity版本,每个Unity版本都包含两个版本的Mono。一个旧版本(Mono)嵌入到编辑器和播放器中。另一个新版本(MonoBleedingEdge)用于运行工具和测试。此MonoBleedingEdge版本可通过启用实验性播放器设置在编辑器和播放器中使用。


Mono解压后:红框是需要操作的文件夹

 

参考文章使用xxtea加密算法,若是有代码加密算法能力的也可以自己编写加密算法,我是没有这个能力,这里依然使用这个算法,这里直接给出下载链接

C语言版本xxtea算法:https://github.com/xxtea/xxtea-c

.net版本xxtea算法:https://github.com/xxtea/xxtea-dotnet

C语言版本用于重编译Mono时解密,.net版本用于unity加密

 

3、mono添加加密算法

在下载好xxtea后,复制xxtea.c和xxtea.h两个文件到开始下载的mono的源码里,具体位置在mono/metadata文件夹下。

然后再用vs2010打开msvc/mono.sln,将上面的xxtea的两个文件添加到libmono里,并找到libmono下的image.c,添加xxtea的头文件。这里我添加之后,上面的#include <config.h> 会有红线,这里对于有强迫症的我非常想解决掉,可又不懂C的我,最后放弃了,最后发现,就算出现红线,最后还是能够编译成功,所以不用担心

 

然后Ctrl+F搜素mono_image_open_from_data_with_name函数,这个函数就是mono去加载Assembly-CSharp.dll的入口,需要在加载的时候添加解密方法,因为这里是针对unity的程序加密,大佬们是针对单个名称来找到dll。

    if (!data || !data_len) {
        if (status)
            *status = MONO_IMAGE_IMAGE_INVALID;
        return NULL;
    }

    //Decrypt
    if (strstr(name, "Assembly-CSharp.dll") != NULL)
    {
        const char *key = "Test"; //这里是密钥
        data = (char*)xxtea_decrypt(data, data_len, key, &data_len);//在这里解密
    }

    datac = data;//解密之后把解密后的代码数据赋值给datac

 

首先设置libmono为启动项,配置选Release_glib,到此为止,需要修改的地方已经完成,保存之后,找到vs2010的命令提示窗口编译解密mono.dll,

 

 

4、Mono编译:

使用vs2010的命令提示窗口编译解密mono.dll时,建议32位和64位各编译一个,编译之后备用,若是加密方式不变,就不用每次都编译解密mono.dll

为什么用VS2010,资料显示unity使用的是2010版本的,至于其他版本大佬们都没有测试成功,各种错误,我也不懂C,所以放弃了修改,还是乖乖使用大佬的方式

1、使用命令行窗口执行mono.sln

注:经测试在选择编译命令工具编译Dll文件的时候,选择带    X64的兼容工具命令提示      编译的始终是64位Dll
                                                                                   选择不带    X64的兼容工具命令提示   编译出来是32位的Dll

 

2、首先进入   解压目录/msvc,mono.sln存放的文件夹位置,

3、执行 msbuild.exe mono.sln /p:Configuration=Release_eglib

 

编译的时候什么都不用操作,耐心等待完成就可以

打包之后的mono.dll保存在buildsàembedruntimesà(win64/win32),使用的时候只需要选择对应的dll即可。

5、unity打包

解码mono.dll准备好之后,开始Unity配置:参考大佬文章,先创建编辑器菜单打包。

在使用的时候先把下载的.net版本的xxtea导入到unity中,对unity编辑器操作需要把代码文件放到Editor文件夹中,并且引用命名空间:using UnityEditor;

    //创建编辑器菜单
    [MenuItem("Build/win x86")]
    static void BuildWindows_x86()
    {
        //编译32位程序
        BuildWindows(BuildTarget.StandaloneWindows);
    }

    [MenuItem("Build/win x64")]
    static void BuildWindows_x64()
    {
        //编译64位程序
        BuildWindows(BuildTarget.StandaloneWindows64);
    }

    #region windows打包
    static void BuildWindows(BuildTarget _bt)
    {
        string path = EditorUtility.SaveFilePanel(_bt.ToString(), EditorPrefs.GetString("BuildPath"), PlayerSettings.productName, "exe");
        if (string.IsNullOrEmpty(path))
            return;

        BuildPlayerOptions _buildOptions = new BuildPlayerOptions();
        _buildOptions.locationPathName = path;
        _buildOptions.scenes = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes);
        _buildOptions.target = _bt;
        BuildPipeline.BuildPlayer(_buildOptions);

        //加密
        EncryptAssemblyCSharp(path);

        //替换解密mono.dll
        ReplaceMonoDll(path, _bt);

        Debug.Log("打包路径:"+path);
        int num = path.LastIndexOf("/");
        path = path.Substring(0, num);
        EditorPrefs.SetString("BuildPath", path);//编辑器模式下,存储打包路径
        EditorUtility.OpenWithDefaultApp(path);
    }
    #endregion

    //XXtea加密
    static void EncryptAssemblyCSharp(string path)
    {
        string acsPath = path.Replace(".exe", "_Data") + "/Managed/Assembly-CSharp.dll";
        byte[] _readByte = File.ReadAllBytes(acsPath);
        string key = "Test";//测试密钥,需要和解密密钥相同
        byte[] encypt_data = Xxtea.XXTEA.Encrypt(_readByte, key);
        File.WriteAllBytes(acsPath, encypt_data);//把加密后的代码流数据保存到dll文件中
    }

    //替换为含解密的mono.dll
    static void ReplaceMonoDll(string path, BuildTarget _bt)
    {
        string _mdPath = path.Replace(".exe", "_Data") + "/Mono/EmbedRuntime/mono.dll";
        byte[] _readByte = File.ReadAllBytes(  "D:/Plugins/mono.dll");//把解密dll文件读取到电脑,写入程序中的dll中。
        File.WriteAllBytes(_mdPath, _readByte);
    }

 

保存之后编辑器界面会出现Build菜单,选择相对应的程序进行打包。

6、测试加密

打包之后使用反编译工具测试,无法读取dll中的代码。

运行程序成功。我使用的2017.2的unity版本,unity高版本没有了mono.dll,有一个mono-2.0-bdwgc.dll,应该是版本升级,高版本的mono源码没有编译成功。把mono.dll的数据流读出来保存到mono-2.0-bdwgc.dll中,测试无法使用。

                   2017.2 运行成功

 

                2018.3  mono.dll

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值