Unity3D 游戏加密解密那些事

0x01 加密

加密主要是为了防止美术资源被窃取(换皮)和代码被恶意修改(外挂辅助,广告,二次打包)

1.资源的加密

先说说Unity加载资源的方式,第一种Resources.Load,第二种AssetBundle。

第一种是Unity缺省的资源格式,如果对这个资源进行加密,Unity将会无法识别

第二种是先通过BuildPipeline.BuildAssetBundle把资源打成AssetBundle,在对AssetBundle进行加密。加载资源时,用WWW把加密后AssetBundle下载下来,进行解密,解密后在通过AssetBundle.CreateFromMemory动态创建出AssetBundle进行解密。

 

2.代码的加密

Unity是一个基于Mono框架的跨平台游戏开发引擎,Unity所使用的Mono属于Mono开源项目的分支

在Unity中,我们写的代码会编译到Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll(这个文件不一定有,Plugins或Standard Assets中的代码会编译到这个文件里)

iOS平台:目前新版Unity用L2CPP方式编译的游戏已经看不到这2个文件了,代码被编译到ios navite代码中了,所以在iOS平台下就不考虑代码加密了。

Android平台:依旧能在\assets\bin\Data\Managed\ 目录下找个这2个文件

第一种是对代码进行混淆,虽然有几个混淆软件CodeGuard、CryptoObfuscator、de4dot...可以用用,但是有很多限制,保护代码的作用不是太大

第二种是对Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll进行加密(有一定难度,需要自己从新编译修改Mono库)

先下载Unity-Mono源码:https://github.com/Unity-Technologies/mono 直接下Zip包(注意Tag版本与开发用的Unity版本要相同)

找到/mono/metadata/image.c这个文件查看mono_image_open_from_data_with_name这个方法

MonoImage *
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;
	}
	datac = data;
	if (need_copy) {
		datac = g_try_malloc (data_len);
		if (!datac) {
			if (status)
				*status = MONO_IMAGE_ERROR_ERRNO;
			return NULL;
		}
		memcpy (datac, data, data_len);
	}

	image = g_new0 (MonoImage, 1);
	image->raw_data = datac;
	image->raw_data_len = data_len;
	image->raw_data_allocated = need_copy;
	image->name = (name == NULL) ? g_strdup_printf ("data-%p", datac) : g_strdup(name);
	iinfo = g_new0 (MonoCLIImageInfo, 1);
	image->image_info = iinfo;
	image->ref_only = refonly;
	image->ref_count = 1;

	image = do_mono_image_load (image, status, TRUE, TRUE);
	if (image == NULL)
		return NULL;

	return register_image (image);
}

第一个参数char *data这个指针指向运行时Assembly-CSharp.dll和Assembly-CSharp-firstpass.dll的内存地址, 可在该方法内添加或调用对data解密的算法

关于Unity-Mono的编译参考这篇文章吧 Unity3D-重新编译Mono加密DLL 

0x02 解密

1.AssetBundle加密了那么加密算法就在Assembly-CSharp.dll或Assembly-CSharp-firstpass.dll中,用ILSpy或Reflector C#反编译工具就能看到源码,找到WWW下载AssetBundle的地方就能找到加密算法。

2.dll加密用IDA类似的反汇编工具加载libmono.so这个文件,搜索到mono_image_open_from_data_with_name这个方法,简单的分析一下就可以找到加密算法。也可以用IDA动态调试,忽略加密算法,dump出解密后的dll文件(动态dump比静态分析要容易简便,但静态分析可以看看别人用的加密算法,同时也能提高自己的分析能力)

3.现在客户端主流的加密也就这样了,但是Android平台下用IDA动态反编译调试一下就破解了。。针对Android平台继续提高破解门坎的话就是隐藏Mono.so中ELF头的section数据,同时添加Anti-Dump(反dump,因为在动态调试下破解者可以跳过你的加密过程,直接把解密后的内容从内存中dump出来)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值