对 u3d 项目生成的Dll进行加密


Hello,我是KitStar

以下文章整理的不对。还请见谅。


如果您碰到什么其他问题的话,欢迎来 我自己的一个 讨论群`559666429`来,大家一起找答案,共同进步

详细介绍U3D项目加密解密方式。可以保证的说,只要你认真看完。肯定就会成功。(毕竟这是我在坑里滚出来的经验大哭


          U3D打包应用之后总是让人头疼,游戏遭到破解与反编译是研发的人最不愿意看到的。自己的辛苦劳动成果被人随意窃取与利用,对这些咬牙切齿的痛恨。所以我们需要加强自身的反破解技术力量。不过,这东西蒙的过君子蒙不过小人,这世上没有破解不了的东西,道高一尺魔高一丈,我们做的只是让破解更加困难而已。让那些破解的人付出点代价才能得到他们想要的,如果他们觉得代价太高,看不清前面的道路,他们就有可能放弃,然后我们的目的达到了。

         对付反编译,比较成熟的方案无非就两种,一种是加密(加壳),一种是混淆(详细链接)。前一种方案,就是对U3D编译出来的dll文件进行二次加密。后一种,就是把程序的可读性,降低到令人发指的程度。当黑客拿到源代码后,也是气血上涌,眼前发黑。好的混淆,需要花极大的精力,才能还原。当他攻破的时候,我们改改程序再混淆,重新发布就又够他折腾的了。 Unity C#代码部分的加密,很多人说混淆,虽然有几个混淆插件CodeGuard、CryptoObfuscator、de4dot...可以用用,但有混淆就有反混淆(de4dot基本都可以搞定),有加壳就有脱壳,有加密就有解密...加密只是提高了门槛提高了难度,而解密只是时间的长短而已。


        编译自己的Unity项目,找到 /Data/Managed/Assembly-CSharp.dll ,对它进行加密,可以自己写个小程序,把Assembly-CSharp.dll转换成字节流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/   官网地址:http://www.bouncycastle.org 
Crypto++(C++版) 代码下载:http://sourceforge.net/projects/cryptopp/files/cryptopp/   官网地址:http://www.cryptopp.com/


        

             安卓端:Unity3D基本客户端的多数代码都会以dll文件形式存下来,功能都在Assembly-CSharp.dll文件中。

                            

                 当游戏应用被开启时c#vm(也就是mono的虚拟机)会去加载所有dll,从而开始运行真正的程序画面了。而破解的很大一部分都是通过解压apk后拿到主逻辑dll,对dll进行反编译,然后修改后重新编译,再放入apk重新签名打包。所以我们需要针对dll进行加密,以防止他们反编译dll(反编译工具链接:Reflector9VSPro,已经破解)。

                 加密一个dll文件非常容易,无论你用什么算法都行,但是在哪解密呢?答案是libmono.so。


            

          libmono.so是mono的核心程序,它承载了加载解析dll和虚拟机运行的功能。所以说libmono.so是关键,我们需要修改mono内核程序并重新编译它。


        PC端:Pc端与安卓同理,只是不同文件。用于PC加载解析dll和虚拟机运行的文件是在程序打包之后下Mono文件夹的mono.dll文件。所以Pc中mono.dll是关键。我们需要修改mono内核程序并重新编译一个mono.dll.   而在这个dll中将存在这解密Assembly-CSharp.dll文件的代码。

image


那么下来说到底怎么加密解密喽!!!!!!!!!!


PC端加密解密步骤:


一,加密Assembly-CSharp.dll


在阅读这篇文章之前,我在处理mono加密问题时,也是参考了雨凇的文章,所以建议先看一下雨凇写的关于加密Dll的文章:

1.Unity3D研究院之Android加密DLL与破解DLL .SO

2.Unity3D研究院之Android二次加密.so二次加密DLL

假装读者已经看过上面的两篇文章了,下面我会记录一下我做的整个加密流程。

一.选取加密Dll的算法

    我们主要目的是对程序集:Assembly-CSharp.dll 进行加密,然后修改mono源码,在mono加载Dll的时候进行解密。显然我们需要一种可逆、对称的加密算法,其实这类算法很多,如DES、TEA、XXTEA等,一般这类对称秘钥算法的安全性都是基于秘钥的(Key),所以如何在mono解密是保护自己的秘钥就十分重要了。我目前使用的是XXTEA,实现的话不清楚,但是github上有开源实现,所以直接拿来用了:xxtea-c

    1.先用Unity导出一个PC工程,在工程路径 xxxxx\xxxx_Data\Managed\Assembly-CSharp.dll ,这个文件就是需要我们替换的程序集啦.找到之后,等待备用。

    2.编写加密Dll工具,大家可以把上面开源xxtea项目中的源码:xxtea.h、xxtea.c 和下面自己要写的的encryptDll.c代码放在同一目录,用MinGW(相关链接)下的gcc编译就可以了:gcc xxtea.c encryptDll.c –o EncryptDll

encryptDll.c代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "xxtea.h"

#define SIZE 1024*1024*10
void main() //命令行参数
{
    FILE *infp = 0;//判断命令行是否正确
    if((infp=fopen("Assembly-CSharp.dll","rb"))==NULL)
    {
        printf("Assembly-CSharp.dll Read Error\n");//打开操作不成功
        return;//结束程序的执行
    }

    //char buffer[SIZE];
    char* buffer = (char*)malloc(sizeof(char)*SIZE);
    memset(buffer,0,sizeof(char)*SIZE);

    int rc = 0;
    int total_len = 0;

    total_len = fread(buffer , sizeof(unsigned char) , SIZE , infp);
    printf("Read Assembly-CSharp Successfully and total_len : %d \n" , total_len);

    //加密DLL
    size_t len;
    char* key = "123456";
    char *encrypt_data = xxtea_encrypt(buffer,total_len, key, &len);

    printf("Encrypt Dll Successfully and len : %d\n" , len);

    //写Dll
    FILE* outfp = 0;
    if((outfp=fopen("Assembly-CSharp_encrypt.dll","wb+"))==NULL)
    {
        printf("Assembly-CSharp_encrypt.dll Read Error\n");//打开操作不成功
        return;//结束程序的执行
    }

    int rstCount = fwrite(encrypt_data , sizeof(unsigned char) , len , outfp);
    
    fflush(outfp);

    printf("Write len : %d\n", rstCount);

    fclose(infp);
    fclose(outfp);

    free(buffer);
    free(encrypt_data);
}


         此时,再把你需要加密的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的解密。

注意:由于笔者在编译的时候碰到各种坑。最后总结下来最好用VS2010进行编译mono,反正用vs2015是各种坑。

          Unity是基于Mono的,地球人都知道...它是开源的 代码下载:https://github.com/Unity-Technologies/mono
直接下Zip包(注意Tag版本与开发用的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>。

unity防反编译 windows平台加密dll

2,再到image.c文件中找一个方法:mono_image_open_from_data_with_name。这个函数就是mono去加载Assembly-CSharp.dll的入口,也就是说我们需要在这里添加我们说需要的解密函数。

第一个方法mono_image_open_from_data_full内实际调用了mono_image_open_from_data_with_name
第二个方法mono_image_open_from_data_with_name的第一个参数char *data这个指针指向运行时Assembly-CSharp.dll的内存地址,
可在该方法内添加或调用对data解密的算法,然后将解密后的data再赋给datac
关于MonoImage这个结构体,它的定义是typedef struct _MonoImage MonoImage;  而_MonoImage这个结构体,它的定义在 /mono/metadata/metadata-internals.h 中
最后就是编译Mono了,编译部分我就不说了自行参看官方说明

该方法虽然是修改Mono内核,偏底层了些,但并不是破解不了,只是要比反混淆的难度高那么一丢丢..

因为这里是针对unity的程序加密,我们完全可以针对单个名称来找到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;

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

	//这是添加的代码,开始   你也可以换成自己想要的解密方法
	if (strstr(name, "Assembly-CSharp.dll")) {
	    char* key = "123456";
		size_t len;
		char* decryptData = (char *)xxtea_decrypt(data, data_len,key, &len);

		int i = 0;
		for (i = 0; i < len; ++i)
		{
			data[i] = decryptData[i];
		}
		g_free(decryptData);

		data_len = len;
	}
	//这是添加的代码,结束

	datac = data;

3,添加完解密方法之后,我们开始编译mono.dll文件。

unity防反编译 windows平台加密dll

a、打开Visual Studio Command Prompt(2010)

b、进入mono-unity-4.5\msvc目录

c、执行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。发现无法编译。


目前测试中:可以成功编译的由,unity-mono-4.6。unity-mono-5.1。unity-mono-5.5.




安卓端加密解密步骤:


请看下一篇更加详细的文章:

Unity3D放破解反编译。DLL加密,mono解密。全程详解。



Ubuntu安卓环境配置:
1,
sudo gedit ~/.bashrc
2.

NDK_ROOT=/home/liaki/NDK/android-ndk-r10e
NDK=$NDK_ROOT
ANDROID_NDK_ROOT=$NDK_ROOT
export NDK_ROOT NDK ANDROID_NDK_ROOT


3,
source ~/.bashrc
source ~/.bashrc


使用APKTool从新打包APK相关命令:

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

Unity防破解 —— 加密Dll与Key保护

Android Unity 加密大事記,比较全面的教程

http://blog.csdn.net/ww_bin/article/details/45315321

ubuntu下安装android ndk

ubuntu下编译mono并安装

Unity3D-重新编译Mono加密DLL


ubuntu安装和查看已安装

Unity3d 加密 Assembly-CSharp.dll (Android平台) 全记录

Unity 3D Android对dll加密和重编译mono源码进行解密

Unity3D DLL加密


编译unity-mono( 写给超级初学者的朋友)

Android apk反编译及重新打包流程




  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值