Unity游戏引擎开发者联盟

 找回密码
 立即注册
查看: 195|回复: 20

[随心记] 如何防止Unity3D代码被反编译?

[复制链接]
发表于 2021-4-12 09:27 | 显示全部楼层 |阅读模式
如何防止Unity3D代码被反编译?
发表于 2021-4-12 09:35 | 显示全部楼层
加密原理(无需Unity源码):
1. IDA Pro打开libmono.so, 修改mono_image_open_from_data_with_name为
mono_image_open_from_data_with_name_0,
2. 替换实现mono_image_open_from_data_with_name,
extern mono_image_open_from_data_with_name_0(...);
mono_image_open_from_data_with_name(...) {
    MonoImage *img = mono_image_open_from_data_with_name_0(...);
    //发现数据文件头不是DLL前缀则解密 img->raw_data, 相应修改img->raw_data_len
    return img;
}
3. 重新打包libmono.so; 替换Unity3D中的android下的版本.
4. 另外写个加密的工具,植入构建环境(MonoDeveloper或VS,添加一个打包后Build Phase来加密DLL); (IOS下禁用JIT固采用AOT编译,DLL中没有逻辑代码,所以无需操心);



从AndroidManifest.xml中可以看出,腾讯的改造应该是修改并替换了入口的classes.dex,把以前的入口 UnityPlayerProxyActivity替换为com.tencent.tauth.AuthActivity. 然后去加载了自定义的几个so: libNativeRQD.so. 周全考虑,为了防止第三方委托libmono去做解密而做了防护措施. 具体实现我还没做深入分析, 应该也是老套路.

libmono.so中的mono_image_open_from_data_with_name也被替换成了mono_image_open_from_data_with_name_0.



解密(android):
方法一: ROOT android系统(最好是一部手机,别搞模拟器,慢死), 挂载LD_PRELOAD的API hook来实现.


方法二: 内存特征码提取,简单高效无敌; 机器能读,你就能读;

JVM, CLR, AS3之类游戏通通秒破。有兴趣看我微博或留言: codex的微博_腾讯微博
发表于 2021-4-12 09:39 | 显示全部楼层
网易云易盾移动游戏安全技术专家陈士留在2018年Unity技术路演演讲内容中对这个问题有过比较详细的介绍,摘录如下:
防止Unity3D代码被反编译其实就是常见的Unity手游风险中的破解风险。
一、Unity面临的破解风险
Unity的破解风险主要有Unity mono脚本解密、Unity il2cpp脚本解析、Assetbundle资源篡改这三项。
1.Unity mono脚本解密:
以下两张图为mono脚本文件的二进制形式及源码转换。




2.Unity il2cpp脚本解析:
以libil2cpp.so和global-metadata.dat作为输入,使用Il2CppDumper即可进行解析:


解析出来的效果如下所示,类名、函数名以及对应的偏移都能够被解析出来:


目前iOS中还没有能够解析为源码的工具,但是如果可以解密或解析Android脚本,将会大大方便iOS的破解。因此Android的有效脚本加密非常有必要。
3.Assetbundle资源篡改:
透视功能可让使用修改版的玩家获取不对称优势。如下所示的某枪击游戏,将其中Assetbundle资源里面的材质属性修改为透明,即可达到透视的效果。


除了资源被篡改的风险外,游戏中还存在资源被竞品盗取、分析的风险。


4.存档数据被修改


某些游戏存档数据以明文形式存在,如果这些数据不去服务端校验,或者是单机游戏的话,则存在巨大的安全风险,游戏的各种属性可以直接修改。
如何保护Unity安全?很多开发团队可能也有自己开发加固保护系统的打算,如果要做好这套保护系统,需要解决很多问题,主要包括以下四个:
第一、保护方案自研成本比较高,需要不断调研、不断改进,不但需要了解破解流程,还需要深度掌握Unity引擎的运行原理。
第二、安卓的兼容性问题,安卓设备碎片化严重,系统版本升级、用户环境多样化。需要不断完善解决方案。网易在这一块积累了很长时间,才开发出一套在性能、兼容性和安全强度都满足的保护方案。如果游戏开发团队自研,兼容性会占用团队大量时间,降低游戏核心逻辑开发速度。
第三、对于破解来说,本身保护工作是一个矛和盾的过程,是不断升级和不断对抗的过程。如果游戏开发团队要去自研保护系统,需要分析市面上的破解工具,并不断分析他们破解的方法,然后才能不断提高整个保护系统强度。
第四、第三方服务的兼容性,游戏现在越来越是一个精细化开发的模式,很多游戏团队只做一些核心的逻辑玩法的开发,所以保护就需要兼容支付模块、热更新方案及质量跟踪等各种第三方服务。而兼容这些第三方的服务,又给游戏开发团队带来了很大的挑战。
综上所述,如果游戏开发团队自主开发保护方案肯定会面临很大技术和资金挑战,所以不建议自主开发保护方案。


二、那么易盾是怎么防止Unity3D代码被破解的呢?


网易云易盾能够提供Unity mono DLL脚本加密、IL2CPP 加密、Assetbundle加密等加密解决方案!


通过修改或者HOOK mono_image_open_from_data_with_name能够对DLL脚本加解密。mono_image_open_from_data_with_name是CSharp 脚本的加载函数,如果CSharpDLL脚本做了加密,需要在这个函数执行之前解密。因此只要在这个函数这里下断点或者HOOK,就可以解密出原始DLL,而不需要逆向加密算法。需要注意的是,这里有个memcpy拷贝操作,mono会把解密后的DLL在内存中留存一份拷贝。
Unity mono DLL脚本加密经历了三代的技术演进。


第一代加密直接对DLL文件进行加密,在mono_image_open_from_data_with_name函数开始处解密。对于这个的破解方法很简单,PE结构的文件,以4d 5a90 00这四个字节为magic head,这可以做为CSharp DLL脚本的特征,只要搜索0x905a4d这个数值就可以了,由于烧饼修改器是使用10进制数值,将其转换成10进制值:9460301。因此解密门槛很低,只要使用修改器就可以解密。


第二代加密基于第一代加密的明显弱点,针对解密加强了防护。解密后,把下图所示的PE头抹掉,使得修改器无法定位到脚本位置。因此解密门槛比较高,需要非常强的逆向开发能力才能破解。
第三代加密针对Csharp 函数做了加密,也就是方法级加密,需动态解密。


原始未加密dnspy函数解析结果
函数加密后dnspy函数解析报错


IL2CPP加密
Il2cpp脚本信息以lib2cpp.so形式存在,结合global-metadata.dat文件内的符号信息,即可进行解析,因此需要对libil2cpp.so做so加壳,如下图所示,原始libil2cpp.so用IDA可以看到475个导出函数:


加固后的libil2cpp.so导出函数则为空:


Assetbundle加密
Assetbundle未加密时,Unity Studio可解析出各种资源:


对Assetbundle加密后,Unity Studio就无法解析了:


三、易盾保护方案特点
网易易盾保护方案具有纯Native保护、对引擎SO做加壳、兼容性和稳定性高、性能影响小、支持Windows、Linux、Mac三平台加固等性能特点。
1.纯Native保护
游戏dex内部都是第三方SDK以及游戏内部不涉及到游戏逻辑的SDK。如果对DEX加壳的话,一方面容易造成Android碎片化,导致dex加壳会降低app的兼容性;另外Android存在Dalvik和Art两种虚拟机,所以dex加壳会为了兼容2种虚拟机而增加处理成本,从而导致启动耗时增加比较厉害。阿里和腾讯都有DEX加壳服务,但是支付宝、微信都没做DEX加壳。支付宝和微信的安全问题应该是所有APP中间最严重的,他们都没做DEX加壳,这很能说明问题,此外所有腾讯的游戏都没有做DEX加壳。所以如果手游保护需要依赖于DEX加壳的话,兼容性和安全性都是很难保证的。因此建议游戏不要使用DEX加壳。
网易易盾可以提供纯Native保护,使游戏保护不依赖DEX加壳。DEX加壳和纯Native保护优缺点比较如下:
2.对引擎SO做加壳
基本上所有的破解都依赖于对引擎so的逆向分析,如果对so进行了加壳保护,会大大增加游戏被破解的门槛。除了对引擎SO加壳,网易易盾还会对敏感函数代码做校验。
3.兼容性和稳定性高
兼容强的原理在于所有保护都在SO层,不会对DEX进行修改,有效避免了Android碎片化导致的兼容问题。网易易盾的兼容性极高,可以兼容从Android 2.3到Android 9.0所有版本系统、所有模拟器以及所有游戏引擎使用的指令集。
手游保护的稳定性,需要遵循如下发布流程:
1. QA测试:在200台手机上以及各种模拟器上测试;
2. 预线上测试:将安全模块集成到日活1000的APP上线测试2周;
3. 版本发布:前面2轮都测试稳定后,正式发布;
4. 线上回归:先在内部比较小的游戏上线测试,确保稳定性。
4.性能影响小
易盾保护方案还具有性能影响小的特点,无论是CPU占用、内存占用、启动时间、电量消耗等方面的影响几乎都可忽略不计。
陈士留演讲全文请点击这里查看。

可点击查看网易云易盾手游加固保护介绍及免费试用。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
发表于 2021-4-12 09:48 | 显示全部楼层
1: 去下载unity3d对应版本mono库源码
2:unity3d逻辑代码dll为Assembly-CSharp.dll 找到mono源码处理这个dll的函数(网上一大堆自已找)这里处理解密, 修改好
3:下虚拟机在对应平台重新编译mono库
4: 出包更换Assembly-CSharp.dll(这里可以处理二进制加密)和对应平台的mono库 重新签名 第2步是解的就是这里加的密 这样外边的Assembly-CSharp.dll如果不知道你的加密方式就没法破解,如果想知道 就得反编译你的mono库 反出来是机器码 要花时间去研究
发表于 2021-4-12 09:55 | 显示全部楼层
如果你没有Unity的Source License,这个问题我觉得基本是无解的。
对于iOS平台AOT后Strip掉IL可能有用,但其他平台基本没什么办法。还有一个思路是加壳,但这个至少在移动端上我没试验过,而且基本上也是道高一尺魔高一丈的事情。
还有一个是把一些关键代码写成Native插件,但这样做我觉得完全就没有使用Unity的优势了,所以也不是很推荐。

如果是涉及网络的游戏,另一个相对有效的解决方案是把逻辑放在服务端,基本上不给客户端Gameplay逻辑层的信任,客户端只负责只发送具体操作。对于非在线游戏我确实没看到什么有效的解法。

个人觉得么,也不要太费劲折腾了,人家要搞你总是有办法的。就算你不用Unity,真的高手是Native Binary一样破给你看的。
发表于 2021-4-12 09:57 | 显示全部楼层
等Unity自带的IL2CPP,目前只支持WebGL和iOS,全平台要等,混淆加密什么的太容易破
发表于 2021-4-12 10:04 | 显示全部楼层
最好的加密手段就是把逻辑都放到服务器上,客户端要破解总能破解,在客户端研究加密纯属浪费时间。
发表于 2021-4-12 10:12 | 显示全部楼层
一个游戏能不能被破解不取决于这个游戏有多么牛b的防破解技术,而是取决于有没有破解价值。
发表于 2021-4-12 10:12 | 显示全部楼层
除非是用自己开发的引擎否则不可能(用自己开发的也会被高手攻破,但是他破了没用,你把EA的寒霜引擎破解了又能怎样?能用它开发游戏?)。U3D让程序工作量少了几十甚至几百倍,这样的代价肯定是有的。要考虑的是你项目的核心价值资源是什么?既然代码保不住,那就在别的地方押注,比如和顶级美术完美对接的游戏剧情和玩法,这个即使被破解也是偷不走的
发表于 2021-4-12 10:17 | 显示全部楼层
受邀~
我们是最大的Unity技术社区, 也是Unity的最佳合伙伙伴, 也是Unity商业总代理.

Unity客户端加密属于一个商业性的问题.
如果你是unity商业话用户可以联系我, 这边帮你找到unity原厂人员帮你解决(收费的).
一般Unity项目加密,针对不同的客户端,web & android & ios .
不同的客户端加密方式不同.
大概的价格区间分别在: 5-10w左右.
需要你提供客户端项目包, 然后这边给你加密好.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity游戏引擎开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2021-5-8 21:05 , Processed in 0.175345 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表