unity 修改Mono反破解加密Assembly-CSharp.dll

本文探讨了Unity中C#代码的加密方法,包括利用自定义加密算法保护Assembly-CSharp.dll,通过修改Mono内核实现更深层级的安全防护。
解密无非就为了 修改游戏功能数据、提取游戏资源、加入自己想加的广告...
加密就是保护游戏不被恶意修改,我经常看到有人说:”加什么密,你以为自己写的代码很NB?见不得人?“。
我只想说,加密并不是不想让别人看到我的游戏逻辑代码,而是不想别人去恶意的修改自己做的游戏罢了...

先说下关于Unity C#代码部分的加密(Android和IOS有时间再细说),很多人说混淆,虽然有几个混淆插件CodeGuard、CryptoObfuscator、de4dot...可以用用,但有混淆就有反混淆(de4dot基本都可以搞定),有加壳就有脱壳,有加密就有解密...加密只是提高了门槛提高了难度,而解密只是时间的长短而已。
Unity下对C#保护措施并不是很多,加壳就别想了,混淆也有限制,混了和没混一样。

除了混淆,我们也可以尝试其他的保护措施,比如下面的方式:
Unity是基于Mono的,地球人都知道...它是开源的 代码下载:[url=]https://github.com/Unity-Technologies/mono[/url]
直接下Zip包(注意Tag版本与开发用的Unity版本要相同)


编译自己的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版) 代码下载:[url=]https://github.com/bcgit/[/url]   官网地址:[url=]http://www.bouncycastle.org[/url] 
Crypto++(C++版) 代码下载:[url=]http://sourceforge.net/projects/cryptopp/files/cryptopp/[/url]   官网地址:[url=]http://www.cryptopp.com/[/url]

有人说.net自带了安全类库,确实是在System.Security.Cryptography下有一些常用的算法,虽然没有上面的类库全,但足以平常使用。
其C#源码也在Mono开源项目中 位置在 /mcs/class/corlib/System.Security.Cryptography/ 若不想了解加密算法可乎略,直接引用里面的方法即可。
如果有闲心的话可以写一个属于自己的加密算法...

此处滤过Hook或是反汇编调试Mono加载Assembly-CSharp.dll的部分...
接着找到 /mono/metadata/image.c 查看下面两个方法
  1. MonoImage *
  2. mono_image_open_from_data_full (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly)
  3. {
  4.   return mono_image_open_from_data_with_name (data, data_len, need_copy, status, refonly, NULL);
  5. }

  6. MonoImage *
  7. mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name)
  8. {
  9.         MonoCLIImageInfo *iinfo;
  10.         MonoImage *image;
  11.         char *datac;

  12.         if (!data || !data_len) {
  13.                 if (status)
  14.                         *status = MONO_IMAGE_IMAGE_INVALID;
  15.                 return NULL;
  16.         }
  17.         datac = data;
  18.         if (need_copy) {
  19.                 datac = g_try_malloc (data_len);
  20.                 if (!datac) {
  21.                         if (status)
  22.                                 *status = MONO_IMAGE_ERROR_ERRNO;
  23.                         return NULL;
  24.                 }
  25.                 memcpy (datac, data, data_len);
  26.         }

  27.         image = g_new0 (MonoImage, 1);
  28.         image->raw_data = datac;
  29.         image->raw_data_len = data_len;
  30.         image->raw_data_allocated = need_copy;
  31.         image->name = (name == NULL) ? g_strdup_printf ("data-%p", datac) : g_strdup(name);
  32.         iinfo = g_new0 (MonoCLIImageInfo, 1);
  33.         image->image_info = iinfo;
  34.         image->ref_only = refonly;
  35.         image->ref_count = 1;

  36.         image = do_mono_image_load (image, status, TRUE, TRUE);
  37.         if (image == NULL)
  38.                 return NULL;

  39.         return register_image (image);
  40. }
复制代码


第一个方法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内核,偏底层了些,但并不是破解不了,只是要比反混淆的难度高那么一丢丢...

转http://www.narkii.com/club/thread-330884-1.html



Unity开发Android应用程序时,为了防止代码被编译和资源被窃取,通常会采用本地加密的方式对DLL和资源文件进行保护。同时,为了限制应用程序的使用时间,可以在应用中加入时间锁功能。以下是实现Unity APK本地加密及时间锁功能的详细指南。 ### Unity APK本地加密实现方法 1. **加密DLL文件** 在Unity项目中,所有的C#脚本都会被编译为`Assembly-CSharp.dll`,这是最容易被编译的部分。可以通过修改UnityMono运行时源码,在加载DLL时进行解密操作。例如,在`mono_image_open_from_data_with_name`函数中添加自定义的解密逻辑,使得运行时加载的是加密后的DLL文件[^4]。 加密过程示例(C#): ```csharp // 对Assembly-CSharp.dll进行加密 byte[] data = File.ReadAllBytes("Assembly-CSharp.dll"); for (int i = 0; i < data.Length; i++) { data[i] = (byte)~data[i]; // 简单取加密 } File.WriteAllBytes("Assembly-CSharp_encrypted.dll", data); ``` 2. **资源文件加密** Unity的资源文件如纹理、模型、音频等通常被打包为AssetBundle或直接嵌入APK中。可以通过自定义加密算法对这些资源进行加密,并在运行时解密加载。例如,使用AES加密资源文件: ```csharp // 使用AES加密资源文件 byte[] encryptedData = AES.Encrypt(File.ReadAllBytes("assetbundle"), key, iv); File.WriteAllBytes("assetbundle_encrypted", encryptedData); ``` 3. **使用第三方加密工具** 可以使用如**Virbox Protector**等工具对Unity生成的APK进行整体加密,同时结合**精锐5加密锁**进行授权管理。这种方式不需要修改代码,完全通过工具完成加密和授权流程[^2]。 ### 时间锁功能开发指南 1. **基于本地时间的验证** 可以通过读取设备的系统时间,判断是否在授权时间范围内。例如: ```csharp DateTime expiration = new DateTime(2025, 1, 1); if (DateTime.Now > expiration) { Debug.LogError("试用期已过"); Application.Quit(); } ``` 2. **基于网络时间的验证** 为防止用户篡改本地时间,建议通过HTTP请求获取网络时间进行校验: ```csharp IEnumerator CheckServerTime() { WWW www = new WWW("http://worldtimeapi.org/api/ip"); yield return www; string json = www.text; // 解析JSON获取当前时间 DateTime serverTime = JsonConvert.DeserializeObject<TimeData>(json).datetime; DateTime expiration = new DateTime(2025, 1, 1); if (serverTime > expiration) { Debug.LogError("试用期已过"); Application.Quit(); } } ``` 3. **结合加密锁实现时间授权** 使用**精锐5加密锁**的SDK,可以在加密锁中写入授权时间信息,程序启动时读取加密锁中的时间信息进行验证,确保用户无法绕过时间限制[^2]。 ###
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值