Unity小贴士 导出资源文件和简单加密方式

来源:互联网 发布:mysql 用户权限 编辑:程序博客网 时间:2024/06/07 08:15

原创文章,转载请注明出处。


记得当初开发手游时,在看到了各类软件对IL的强大反编译功能和disunity的解包能力后,跟我同一个组的师兄不禁发出了感叹,“有种不穿衣服走在大街上的感觉”。


可以相信这世界上没有贼,但是却不能不给房间上锁。虽说即使有了锁,有心人仍然能花功夫进来——混淆就有反混淆,加壳就有脱壳,加密还能破解。有许多人以此为乐。但是随着安全手段的增多,破解难度和时间成本也会呈几何级数上升,自然就失去了让人破解的经济意义。


本文要讨论的是Unity资源文件的加密方式。对代码的保护可以参考雨松momo的关于代码混淆的文章:http://www.xuanyusong.com/archives/2664。如果嫌力度不够,还可以对dex加壳,对so加壳等,这里不赘述。


现如今AssetBundle的文件组织方式、压缩算法等已经成了半公开的知识,disunity作为一个开源项目更是成了广大U3D程序员的必备工具。仅仅是因为disunity就不使用AssetBundle显然是因噎废食,因此资源文件的加密某种意义上就是防止AssetBundle被disunity解包。


为了对AssetBundle进行加密,可以分这样两步:


一:和平常一样导出AssetBundle。这个的网上代码有很多。

二:运行一个外置的工具对AssetBundle进行加密。这里贴一个例子。


using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;namespace Encyption{    class Program    {        //157即二进制的10011101,原AssetBundle中每一位都与之进行半加。        const Byte key = 157;        static void Main(string[] args)        {            string str = System.Environment.CurrentDirectory;            string[] ABs = Directory.GetFiles(str+@"\Input");            for (int i = 0; i < ABs.Length; ++i)            {                string fileName = Path.GetFileNameWithoutExtension(ABs[i]);                Byte[] temp = File.ReadAllBytes(str+@"\Input\"+fileName+".assetbundle");                Encypt(ref temp);                File.WriteAllBytes(str+@"\Output\"+fileName+"Encypted.assetbundle", temp);            }        }        //加密函数,这里是一个很简单的例子。更简单的方法还有在最后一位增加一个字符使Disunity解析文件失败等。        static void Encypt(ref Byte[] targetData)        {            int dataLength = targetData.Length;            for (int i = 0; i < dataLength; ++i)             {                //对targetData中的每一byte都和10011101做异或运算。                targetData[i] = (byte)(targetData[i] ^ key);            }        }    }}

这样以后,在Output文件夹中就是加密过的AssetBundle。


我们可以用System.IO.File或者Unity的WWW类等将加密过的AssetBundle作为普通的二进制文件加载进内存,利用File.ReadAllBytes或者WWW.bytes读取其二进制形式。此时,在Unity中对该二进制数组进行加密函数的逆运算(示例代码是最简单的对称式加密,且加密函数就是解密函数)。


二进制文件而在AssetBundleAssetBundle类中有一个方法:AssetBundle.CreateFromMemory。这个方法可以将内存的一段二进制块转变为AssetBundle。对解密后的内存调用此函数后,原来的AssetBundle就回来咯~


另外提供一种比较丧病的思路(我并没有去试),即把所有的脚本、资源部分(C#也看成是脚本)都进行加壳,在mono的本地运行时劫持加载函数去脱壳……似乎好像可以对mono_image_load_file_for_image这样一个函数去动动手脚,或者直接拿Github上的mono去改一下,生成一个特制的运行时……?有路过的大神还望不吝赐教。


嘛,il2cpp以后mono运行时这种东西已经不重要了,应该是的吧?

0 0
原创粉丝点击