本帖最后由 xiaoxin520 于 2016-4-4 02:27 编辑

本文作者七少月,文章中很多观点和技术手段为本人原创,转载请注明出处,由于本人技术水平有限,不当之处,还请斧正。

前言:

由于本人一直以来都比较忙,开班、工作等等事情太多,所以很长一段时间没有发帖。其实我确实想看一看,尤其是Unity3d安卓游戏逆向领域有没有更出彩的文章。可能有些不恰当的说,确实这一段时间以来,虽然也有一些Unity3d安卓游戏逆向的优秀文章,如对金庸群侠传X1.0的数据库解密和功能解锁修改,但无论从数量上,还是从难度上,我都难以满意。不知道是愿意共享的人少了,还是觉得U3D逆向技术太简单了,如果是后一种原因,我只想说,U3D在安全开发的投入和技术发展是难以想象的飞速,如U3D把关键函数引向lua,利用Lualib实现C#与LUA交互,不仅实现热更新,也保护了代码,而lua脚本文件则作为资源文件打包混淆。以上是后话,现在最大的问题在于,即使DLL解密脱壳后,我们依然在静态分析DLL。

难以逾越的鸿沟:

本篇技术文章需要一定的U3D安卓逆向基础,没有的推荐看法总的教程,至少你能用reflector把DLL中一个return hp语句修改为return 99999.在之前我们说过,由于U3D底层并不开源,而且DLL运行在安卓上已经是受到了很大限制,所以在给我们逆向带来比普通安卓的dex和so目标更为明确的同时,也让我们逆向手段带来很大拘束。导致的一个结果就是,我们逆向U3D的DLL,只能使用静态分析,通过搜索,然后修改,最后测试。一直以来,我们认为,只要把关键DLL拿到,即使是网游,也可以进行修改。但以后就不是这个样子,可能以后DLL确实是所谓的关键DLL,但就不做保护地摆在那里,都没有什么作用。如果你一直看我U3D逆向的相关文章,这是继U3D把DLL加密加壳阶段的下一个新的阶段,我称为关键DLL无效的阶段。回到本文,我们好像确实很为难,只能使用静态分析仿佛成了我们一道无法逾越的鸿沟。

Unity3d游戏DLL动态调式与HOOK:

能实现对U3D游戏进行动态调试,是我和法总一直以来的愿望。早先,我写过一篇理论指导性的文章《Unity3d游戏动态调试理论框架》。当然,就在那不久之后,里面的思想相继得到了实现。最具代表性的,就是利用IDA动态调试libmono.so,DUMP下来解密后的DLL。但很可惜,那种动态调试,实质是在动态调试so,离我们当初想实现的真正的DLL动态调试相距甚远,更别提对DLL进行更深层的HOOK。当然,如若想实现DLL能像dex或SO那样进行单步调式,可能还是比较遥远,首先就是没有工具,IDA对安卓DLL的效果很不理想,我们的神器reflector还不提供远程调式安卓DLL的功能,但确实可以存在一些替代性的策略。下面,我们要知道以下几点:

1. 任何一种动态调试,并非一定要实现单步调式才叫动态调式,能实现单步调式是我们最理想的状态,但动态调试都是从log开始的;

2. 把程序在运行时断下来,是动态调试的精髓所在,但也有一些简单的替换性策略,比如我在C#编写的EXE中的代码中,插入一句message.show(“运行到此处”)代码,让程序在运行到我感兴趣的那段代码时弹出对话框。但这个在U3D中实现是很困难的,远没有安卓smali中通过静态注入Alert对话框代码那样简单,因为U3D的脚本代码和组件联系太过紧密,U3D本身更贴近于一个类似于3DMAX的三维设计软件。

3. HOOK本质的意义是注入代码,也是替换程序原本函数,所以DLL的HOOK可以分为内部HOOK和外部HOOK。由于reflector的插件reflexil本身就可以对DLL进行注入类、方法、变量、属性等,通过这种方式的HOOK就是内部HOOK。而外部HOOK,就是在其他DLL,甚至是其他的非C#编写的任何文件去HOOK这个DLL。

说了这么多,理论基础终于讲完了,本篇是基础,只讲解简单的LOG和内部HOOK注入。

准备及样本:

为了方便,我们采用比较简单的berryrush游戏作为样本,该样本在法总教程中存在。

首先,我们需要游戏的关键Assembliy-csharp.dll,当然这个DLL要是解密后的,而且要是真正的关键DLL,当然它要对游戏有决定性作用,而不是里面只有不关键的支持性代码,关键性代码存在于别的地方。其次,我们要把UnityEngine.dll拿出来,一般这个类被处理的很少。然后把它们一起拉到Reflector工具中。下面,我们来认识一下,UnityEngine.dll的UnityEngine命名空间中的Debug调式类。该类有Break、Logstr等方法。如图:

1.jpg (31.23 KB, 下载次数: 2)

2016-4-4 02:24 上传

已经淘汰的U3D开发技术:

由于这些技术过于简单,非常容易被逆向,在现今的U3D中,已经被淘汰

1. 把关键变量写成属性,且可以被外部调用,表现为其关键变量是个属性,存在get_XX和set_XX方法。现今,都是对变量进行不可被调用的声明,也就是为变量,表现为在Reflector中用蓝色长方体作为图标,且往往其声明为protected或private,而不是public

2. 不再存在如GetCoins(),这样明显的关键性函数,即使有,要不代码非常复杂,逻辑特别难懂,要不就是修改了也没用的;

3. 不再存在关键性变量在使用时直接进行赋值语句,如this.coinscount = 0,与上种情况相同

以上说明只是让大家知道,本例中这些情况是存在的。

Debug类的初步使用下断:

我们选择GetCoins()这个函数,我们加一句代码Debug.Break()。那么在IL语言中怎么添加中,首先,我们要注意,在添加指令的时候,指令是call,类型是Method,操作数是Debug.Break()这个函数。

2.jpg (20.45 KB, 下载次数: 3)

2016-4-4 02:24 上传

我们的代码就是:OffsetOpCodeOperand

0ldarg.0

1ldfldSystem.Int32 StrawberryPlayer::coinsCount

6callSystem.Void UnityEngine.Debug::Break()

11ret

然后,我们回编,利用手机版的log工具(会在附件中里有),对其进行log,我们发现游戏并没有停止运行,但是在这句代码被执行时,会给予该代码执行的时间及一些状态,如果下多个这样的断点,是完全可以了解一定的程序运行逻辑的。

3.jpg (30.91 KB, 下载次数: 4)

2016-4-4 02:24 上传

DLL的内部注入HOOK:

首先,我们要知道,HOOKDLL究竟有多大的好处。HOOK就是注入,替换。我们举个例子,上面已经说过,现在关键性的变量都没有get,set,也不在函数中进行赋值,总之一切都在U3D内部逻辑完全,紧密贴合于组件。这就好比是客户端和服务端,如果一直这么双方联系着,会对我们分析和修改带来很大不便。我们注入就好比是中间人,假设我们注入是一个变量,那么这个变量可以去替换一个程序原先使用的变量在函数里出现的位置,我们根本不需要知道原本这个变量如何计算得到,我们只需要定义一下这个中间变量,然后赋值给原先的变量,然后观察程序运行的反应和效果。这样一来,我们就找到了一个突破点,顺着这个点,再继续分析下去。本例中,我选取StrawberryPlayer类中的StartRunning()函数,变量则选取该类里的coinsCount,在游戏中表示金币数,在StartRunning()函数中被赋值为0。

在进行DLL HOOK之前,我们一定要知道,我们通过静态分析,得到的关键类、关键方法、关键变量是什么,任何动态调试,如果没有静态分析时的确定目标,那就是无头苍蝇。本例的关键在刚刚已经写得非常清楚。

接下来,我们在关键类StrawberryPlayer类右键,选择Reflexil2.0(我的该插件版本是2.0),然后选择inject field,即注入变量,这里要注意,注入的变量数据类型要和原本想替换的变量数据类型一致,本例的coinsCount是一个Int32型,变量命名为coinlog。

4.jpg (47.34 KB, 下载次数: 3)

2016-4-4 02:24 上传

注入后,DLL加载会刷新一次,然后你就发现在该类下有了coinlog变量。

5.jpg (34.59 KB, 下载次数: 3)

2016-4-4 02:24 上传

下面,我们到StartRunning()函数中,在代码的尾部添加以下几句代码,也就是先赋值coinlog变量为99999,再让coinsCount=coinlog,最后Debug.Logstr(“金币已做修改”)。对于赋值语句添加是基础内容,可去学习法总教程,对于Debug类使用上述已经说过,这里只给结果:274ldarg.0

275ldc.i499999

280stfldSystem.Int32 StrawberryPlayer::coinlog

285ldarg.0

286ldarg.0

287ldfldSystem.Int32 StrawberryPlayer::coinlog

292stfldSystem.Int32 StrawberryPlayer::coinsCount

297ldstr金币已做修改

302callSystem.Void UnityEngine.Debug::Log(System.Object)

307ret

简单说一下:274-280偏移指令是this.coinlog=99999;285-292偏移指令是coinsCount=coinlog;297-302偏移指令是Debug.Logstr(“金币已做修改”)。注意一下,这里的274等数字是指令所在的相对偏移地址,也就是offset,如果简单用第几句指令的话,应该是第86句-95句。

6.jpg (55.43 KB, 下载次数: 4)

2016-4-4 02:24 上传

我们回编测试,自然游戏初始化的金币就是99999了,用log手机版查看,也非常清晰,可以看到这个函数是何时被调用的。

7.jpg (50.25 KB, 下载次数: 3)

2016-4-4 02:24 上传

下载地址:http://pan.baidu.com/s/1gfdfsbT

android unity hook,Unity3d安卓游戏DLL动态调式与HOOK基础相关推荐

  1. android unity hook,[原创]Unity3d安卓游戏DLL动态调式与HOOK基础

    [原创]Unity3d安卓游戏DLL动态调式与HOOK基础 2016-4-4 02:40 8207 [原创]Unity3d安卓游戏DLL动态调式与HOOK基础 2016-4-4 02:40 8207 ...

  2. android数据包放在,安卓游戏数据包是什么_安卓游戏数据包放在哪里

    现在随着各大游戏厂商的游戏效果越来越华丽,各种游戏也越来越大了.越来越多的游戏也需要用到游戏数据包了,今天小编就和机友们说说关于安卓游戏数据包是什么. 安卓游戏可以分为含数据包的和不含数据包的两个大类 ...

  3. android数据包放在,安卓游戏数据包放哪,怎么使用?

    您可能感兴趣的话题: 安卓 核心提示:正在使用安卓系统手机的朋友们是否知道安卓游戏数据包放哪?如何你还不清楚,就来看看本文的介绍吧. 正在使用安卓系统手机的朋友们是否知道安卓游戏数据包放哪?如何你还不 ...

  4. unity android 播放器,Unity3D 安卓视频播放插件 WRP Android Video Player Pro

    通过这个安卓视频播放插件,你可以在你的Unity3D 项目中针对很容的播放视频. Easily play videos in your Unity Android Projects with this ...

  5. Unity安卓游戏开发:打造7款2D 3D游戏 Unity Android Game Development : Build 7 2D 3D Games

    流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确) |大小:15.4 GB |时长:32h 55m Un ...

  6. gg 修改器游戏被保护_某游戏DLL保护分析,以及偷学一点Unity代码保护思路

    本人虽然是个手残,却非常喜欢尝试各种音游,即使被虐到爆炸也停不下来. 最近看上一款某渊的音游,它的判定线移动打拍的玩法挺不错的,于是乎又手贱买了,然后被虐到体无完肤. 本着至少要给自己爽一下的原则,就 ...

  7. 【Android 逆向】逆向修改游戏应用 ( 分析应用结构 | 定位动态库位置 | 定位动态库中的修改点 | 修改动态库 | 重打包 )

    文章目录 一.应用结构分析 二.定位动态库位置 三.定位动态库中的修改点 四.修改动态库 五.重打包 一.应用结构分析 分析上一篇博客 [Android 逆向]逆向修改游戏应用 ( APK 解析工具 ...

  8. android unity 关闭应用_使用Android Studio在安卓平台Profile Unity应用

    0x00 前言 大家常常会抱怨安卓平台没有一个统一.好用的性能检查工具.不能像iOS的instrument那样方便. 比如,Unity Blog在3年前就已经教大家如何使用instrument来进行性 ...

  9. Unity3D安卓导出包加密学习--加密Assembly-CSharp.dll

    Unity3D安卓导出包加密学习–加密Assembly-CSharp.dll Unity3D安卓导出包加密学习--编译mono http://blog.csdn.net/grimraider/arti ...

最新文章

  1. 不是广告--如何学Java,我说点不太一样的学习方式
  2. python列表怎么写文件_python中以字典为元素的列表怎么写入文本文件
  3. oracle解锁system密码,Oracle System密码忘记 密码修改、删除账号锁定lock
  4. 超低费用将推动BCH在Token系统中脱颖而出
  5. 项目启动时socket自动启动_spring boot 项目在启动时调用接口
  6. 小牛想要进大厂,距离拿百万高薪,进入AI行业你还缺哪些?
  7. Android复习16【材料设计新特性:fragment、RecyclerView】
  8. java中ra怎么解释_JAVA个人相关知识总结
  9. 11input/output
  10. 信息抽取--关键句提取
  11. c# sha1签名 微信_C#微信公众号JS接口签名算法
  12. 小鹏汽车窃密特斯拉实锤?前员工回应:确实上传过30万份Autopilot源码
  13. [3rgb.com开发笔记] 初步设想篇
  14. 一个按钮控制暂停和开始java_《第一炉香》|一个女人的自甘堕落,从控制不住欲望开始...
  15. svn里的branch、trunk、tag的用处
  16. 网路收包流程-网桥的处理流程(br网桥)(四)
  17. 最新布尔教育Blog项目实战 php博客项目实战教程 php实战教程(完整)
  18. Ruby on Rails 入门学习
  19. 新路由3 newifi d2 潘多拉PandoraBox固件,带鸡血驱动
  20. 注册gitLab时报错There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.

热门文章

  1. .Net Core API网站调用支付宝第三方API(实现授权验证、实名认证、银行卡发行银行校验)
  2. Mybatis @Flush注解分析
  3. Altium Designer原理图库引脚名字上横线的含义
  4. 使用vue-cli创建构建vue3项目(npm方式)
  5. 用turtle画国旗
  6. python解奥数题_黄哥Python:Python代码解决一道小学奥数题
  7. Appium自动化测试-iOS模拟器运行
  8. 单片机唱祝你平安c语言,C51单片机蜂鸣器祝你平安音乐
  9. BODAS说明书的中文版与相关资料总结
  10. BBEdit for Mac,专业html文本编辑器