微信5.0 Android版飞机大战破解无敌模式手记

转载: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html

微信5.0 Android版飞机大战破解无敌模式手记

最近微信出了5.0,新增了游戏中心,并内置了一个经典游戏《飞机大战》。游戏其实很简单,但由于可以和好友一起竞争排名,一时间受到大家的追捧,小伙伴们进入“全民打飞机”时代。

ios 版出来不久就被破解出了无敌模式。Android版出后好像一直风平浪静。周末无事,加之看雪zmworm版主邀请,于是花了一天的工夫研究了下。也出了个Android版的无敌模式增强版。具体来说就是无敌、双排子弹加无限炸弹。当然,这个不是重点,我们的重点当然是技术细节啦!

微信的游戏继承了Android版手机QQ游戏中心的思想,也采用插件动态加载方式。具体来说,就是插件及游戏以jar包形式存在,jar包中有classes.dex及其他资源文件,在运行时动态加载资源及classes.dex代码。这样的好处是灵活管理,易于扩展。以后更多的游戏只要上架到微信的服务器,用户就能在微信应用内部下载、安装、运行。具体原理可以参考我2011年的一篇文章《Android类动态加载技术》 。

当然,那篇文章讲的只是基本原理,而微信在代码动态加载方面则走得更远。针对插件的管理及安全,它有一套完整的框架,并自称为sandbox。由于代码有做混淆,加之代码量挺大,所以我仅算管中窥豹,看到的也只是冰山一角。与实际情况有所出入,还请见谅!

一、微信游戏插件的安全校验

其实说实话,微信在游戏插件的安全架构方面花了不少功夫。我能破解并不是利用微信在安全方面的漏洞,而是Android系统本身的安全漏洞。这个漏洞也就是我前段时间发的以为是bluebox上报google的漏洞,后来被证实不是。详情请看《Bluebox Security最新提报Android漏洞的初步探讨》 。

那微信是如何对游戏插件进行加载及安全校验的呢?

飞机大战的游戏插件以jar包的形式,放在微信apk的assets/preload文件夹下:

jar包中包括classex.dex、so本地库及drawable图片资源或者还有xml资源。微信处理插件加载的代码在com.tencent.mm.compatible.loader包中。加载插件资源的类叫做PluginResourceLoader,它是android.content.res.Resources的子类。

而最核心的加载类应该是PluginClassLoader。上面说的PluginResourceLoader也是它的成员变量。它似乎负责整个插件加载的各个环节调度。

Android动态加载类有一个弊端,就是dex文件必须释放为本地文件。这是dalvik虚拟机机制决定的。一直以为google或者dalvik会改,不过似乎到现在还没见改进。释放到本地缓存的dex是很容易受到攻击的,不过微信在这些细节上处理得还挺好,没有明显漏洞。这个后面再说。

PluginClassLoader会在微信安装后第一次启动时,扫描插件的情况,并将插件拷贝到自己应用data下面的app_dex文件夹下。接下来会对插件进行处理。将so库释放到app_lib文件夹下,将jar包中的classes.dex重命名释放到app_cache文件夹下。

在拷贝插件jar包的过程中,会对插件进行第一次校验——签名校验。关于签名校验的原理,可以参看我2011年的另一篇文章《Android APK 签名比对》 。微信的签名校验就是微信APK的签名需要和插件jar包的签名一致。这里我考虑过用bluebox上报的ANDROID-8219321漏洞绕过插件jar包的签名检测。经过一段时间的研究发现了它还有第二次校验。。。

由于是在拷贝之前进行签名校验,所以我考虑过拷贝完成后,直接替换app_dex和app_lib下的文件的方法。发现均不可行。继续分析发现了第二次校验——MD5校验。一开始看到jar包命名就很疑惑,文件名后面一串数字是干嘛的。想过是MD5码,没做验证。直到碰壁之后,才发现了这里的奥秘。后面这一串数字就是jar包的MD5值。插件加载的时候会去解析这个MD5值,并存起来。在加载运行的时候会对这个MD5值进行校验,如果缓存中的文件MD5值不同,会用重新释放apk中的插件覆盖。缓存中的dex应该也有类似的机制。这部分代码分析得不是很透彻,大概原理如此,有感兴趣的朋友可以继续深入。

MD5值作文件名+签名校验,以为着利用ANDROID-8219321漏洞的企图落空了。因为ANDROID-8219321漏洞的前提是apk中文件的文件名需要保持不变,这样才能通过重名文件绕过签名校验。然而只要我们改了插件jar包,MD5值就必须得变,从而导致文件名改变。因此此路不通了。(也许可以通过修改MD5校验和签名校验的smali绕过校验,无奈我暂时没找到具体MD5校验的代码,只能作罢)。

MD5值作文件名+插件签名校验,再加上安装APK本身的签名校验。三重校验保证了微信游戏的安全性。

因此我只能采用《Bluebox Security最新提报Android漏洞的初步探讨》 一文中所述的安全漏洞。此漏洞针对system/app和vendor/app下的apk只会校验manifest.xml文件签名。因此我可以任意修改插件jar包,在重新生成新包之后计算出新包的MD5值,并对新包进行重命名。对于插件的签名校验,则直接通过修改smali代码,屏蔽掉微信签名校验的函数功能,直接返回true:

这就是我们修改插件之后得以正常运行的理论基础及可行性保证。有了上面的理论,我们就可以开始修改游戏了!

二、飞机大战游戏破解

飞机大战这个游戏据说是腾讯一个程序员一周时间开发完成的作品。其实考虑到这个游戏的规模,除GUI和交互设计外,程序员一周时间应该也差不多了。没有太大出入。

此游戏采用的游戏引擎是libgdx。相信做过Android游戏的朋友对此款引擎不会陌生。如果在Android平台开源游戏引擎里,cocos2d当仁不让地排第一的话,那么libgdx也可以当仁不让地排第二了。cocos2d主要采用C++开发,而libgdx则主要采用java方式开发。学习成本低,开发周期短,是它的优势。当然它也是跨多平台的游戏引擎,运行效率方面稍有欠缺但也不错。因此广大的Android单机小游戏都是采用libgdx作为游戏引擎。

微信飞机大战的代码量不大,有兴趣的朋友可以研究下,移植成为一款独立的单机游戏应该也不难。下面我详细介绍下飞机大战游戏破解的技术细节。

第一步就是将飞机大战游戏的插件包从apk中释放出来。我们可以采用反编译APK的方式反编译这个插件包。修改smali代码之后,再打包回jar包文件。如果还有朋友对APK破解流程不熟悉的话,可以参考我以前的一篇文章《APK Crack》 。这里我们主要介绍游戏的架构及破解思路。

解压之后,smali部分其实可以分为两个包:com.badlogic.gdx和com.tencent.mm.plugin.shoot。前面一个是libgdx导入的jar包,这个不是我们关心的内容。我们的重点就在com.tencent.mm.plugin.shoot这个包中。

游戏主要有两个Activity:ShootMainUI和ShootFlashUI。它们都继承自com.badlogic.gdx.backends.android.AndroidApplication,这个类事实上继承自Android系统的Activity。它们一个是主加载界面,一个是我们停留时间最长的游戏界面。当然需要了解,但都不是重点,重点是我们游戏中的各种角色:

这些角色构成了整个游戏的演员,他们都继承自同一个类:GameSprite。相当于游戏引擎中精灵的概念。它们都有生命值、宽高、速度、类型、状态等属性。这些类的定义都在actor子包内。在游戏过程中会对每个精灵做碰撞检测,当你发现你的飞机爆炸时,就是碰撞检测在起作用。顺便说一下,libgdx引擎采用的物理引擎是C++版的box2d,性能非常不错。

好了,我们具体的破解特性,我会以任务的形式一个一个娓娓道来。下面我们接到的第一个任务就是“永久双子弹”!

任务1、永久双子弹!

在玩飞机大战时,双子弹意味着更大的威力。可以消灭更多的敌机,化险为夷。然而在实际游戏中我们只有吃到PROPS_DOUBLE之后才能拥有一段有限时间的双子弹状态。

双子弹属性属于HERO的,对应的类是Player和PlayerActor。Player继承自GameSprite,而PlayerActor则是libgdx中的actor类的概念。两个前者注重状态和属性,后者注重逻辑和动作。

Player在构造函数初始化时就会设置子弹类型:

我们只需要把BulletType从NORMAL改为DOUBLE就可以了。

PlayerActor会对子弹类型进行定时地检测,检测是会将双子弹还原为单子弹。应该是为了处理吃到PROPS_DOUBLE后,一段时间子弹还原的问题。所以我们一并改掉:

OK,双子弹破解任务完成!

任务2、炸弹无限!

炸弹是个好东西,威力无穷。关键时候全靠它清屏,消灭所有敌机!而且它还是刷分利器。当然,只有在它变为无限的时候,我们才能用它来刷分。

这里我试图修改Player的getBombNumber和setBombNumber方法,发现均不行。后来转变思路,只要在使用炸弹后炸弹数量不减少,就能实现无限炸弹的功能。经过代码追踪,最后定位到一处混淆代码处。将-0x1改为了0x0。

修改的结果,在吃到两个炸弹后使用炸弹不会减少炸弹数量。吃一个炸弹时,使用炸弹后炸弹按钮消失,因此无法做到无限。请记住一定要存到两个炸弹之后才能无限炸弹。无限炸弹破解任务完成!

任务3、开启无敌模式!

长生不死一直是我们人类的终极梦想,在游戏中也不例外。iphone版微信也是因为有了飞机大战无敌模式而被各大新闻站点竞相转载。让我们Android版也无敌一下吧~

前面提到了GameSprite是所有角色的父类,在游戏用物理引擎做碰撞检测后,会调用GameSprite类的hit方法。hit方法中将GameSprite的liftCount减一,如果减到0则将状态设置为DEAD。

GameSprite的状态有如下一些:

DEAD
EXPLODING
FLIGTHING
HITING
INVINCIBLE

在飞机正常的死亡过程中,是先HITING,再EXPLODING,再DEAD。FLIGTHING我不清楚干嘛的,INVINCIBLE应该是无敌模式。但是在我的破解里,并没有使用这个模式,而是强制在碰撞检测结果中,把它列在了生死薄之外。至于INVINCIBLE的方式,大家可以试试能不能很好的维护这个状态。

具体来说就是hit方法不管GameSprite是hero也好,enemy也罢,均一视同仁,生命值减一,或者死掉。然而我们可以通过修改smali代码,将hero列在生死薄之外:

其中goto_1标签跳转到return-void。这样我们的hero将永远不会被hit,因此也就无敌啦!

任务4、独孤求败。。。

本以为完成任务3就大功告成了,谁知我们缺遇到了无敌的尴尬——死不了。。。死不了,意味着永远无法结束游戏,永远不会有机会上传自己的得分进入排行榜。哎,现在终于明白为什么独孤求败了。。。

基于此,我们得想个办法触发飞机非自然死亡。想来想去,我还是觉得让飞机自己决定自己的生死最合理。具体就是当飞机飞到屏幕最上方时触发死亡。因为一般情况,我们不会把飞机飞到屏幕最上方,所以误操作概率极低。

通过前面我们知道hero飞机的类就是Player。而Player中有一个函数更新飞机的坐标位置:updatePosition。所以我们可以在这个函数中进行我们想要的操作:

其中0x64就是我指定的y坐标下限100。当飞机坐标y在100以内时,我会把飞机的LiftCount设置为0,然后再将状态设置为EXPLODING。飞机就会爆炸死亡了~
OK,任务完成,打完收工!

三、一些扫尾工作

插件包修改完成后,我们通过apktool,将其打包回jar包。res资源包需要手动添加会jar包中。然后按照第一节所说的,生成jar报的MD5码,重命名jar包。
微信APK也需要按第一节的方法,将插件的签名校验屏蔽掉。编译出classes.dex,替换微信原始包中的classes.dex。
再将APK包中的飞机大战插件换为我们编译出来重命名的这个jar包。

OK,APK准备好了。

由于我利用的是《Bluebox Security最新提报Android漏洞的初步探讨》 一文中所述的安全漏洞,所以安装此APK的过程并不是菜鸟能玩的。。。简单来说,你需要root权限,并能将system分区mount为可写。

然后卸载你原本的微信。将这个apk放到/system/app/文件夹下。稍等片刻,你就是打飞机的高手了!

如需技术交流,请与我联系。新浪微博: @囧虎张建伟

转载请注明出处: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html

附排行榜:

注:游戏作弊有一定的封号风险,请大家慎重使用。本帖只作技术交流,不用于其他任何商业目的。


补充说明(2013.8.15):

有朋友反馈,按照我文中的步骤一步步下来,生成apk push到system/app下,程序无法正常运行起来。强制退出。
请查看log,是否有类似如下错误:

Caused by: java.lang.UnsatisfiedLinkError: Couldn't load CrashMonitorForJni: findLibrary returned null .....
at com.tencent.mm.sdk.platformtools.CrashMonitorForJni.init(SourceFile:26)
at com.tencent.mm.sdk.platformtools.aq.(SourceFile:62)

导致这类错误的原因是有些手机将apk push到system/app下后,安装过程不会释放拷贝so库。
你需要手动将微信lib下对应你手机平台的so库拷贝到/data/data/com.tencent.mm/lib对应的文件夹下。
由于我的手机没这个问题,所以之前没有发现。特在此做补充说明。


补充说明2暨可安装版APK发布(2013.8.18):

本文发出后,得到广大网友的热烈响应。一些网友因本文对软件安全产生了极大兴趣。

许多朋友按照文中的方法破解成功,而也有不少朋友还有一些关键点没有突破。很高兴看到大家在论坛、微博、博客和邮件中与我交流,我也尽量答复大家技术相关的问题。但仍有不少朋友的问题没来得及答复,在此向你们表示歉意!

在大家的提问中,很多朋友希望我能直接提供APK,以供深入研究。之前由于安装步骤过于繁琐,所以一直没有发布APK。

好消息是在网友的不断提问和更多的信息提供之后,我发现最新的微信版本似乎将我文中提及的安全校验机制关闭掉了。因此,我们可以采用重签名的方法得到可以直接安装的APK。值得注意的是:1、插件jar包和APK包都需要签名,且签名一致;2、MD5校验似乎也失效,不用重命名插件包。

(我确信这在我之前破解的版本是不行的,严重怀疑微信是不是把内部debug的版本给放出来了。。。)

APK下载地址:点击下载 。

再次声明:本破解版游戏仅用作技术交流,严禁用于任何商业目的!违者后果自负!

微信5.0 Android版飞机大战破解无敌模式手记相关推荐

  1. android微信7,微信7.0安卓版之初体验

    原标题:微信7.0安卓版之初体验 就在上周末微信 iOS版先走一步更新到了7.0版本,紧跟着微信安卓7.0测试版也上线了,笔者也在第一时间跟进升级到了微信7.0版.通过几天的使用,对新增的功能基本有了 ...

  2. android 8.0发布直播,安卓版微信8.0内测版来了

    原标题:安卓版微信8.0内测版来了 2021年1月21日是微信十周年,微信也第一时间推送了全新的8.0版本,依旧是iOS用户优先,这让不少安卓党羡慕嫉妒恨.不过没有关系,按照以往惯例,安卓内测版会立马 ...

  3. python飞机大战源代码-python版飞机大战代码分享

    利用pygame实现了简易版飞机大战.源代码如下: # -*- coding:utf-8 -*- import pygame import sys from pygame.locals import ...

  4. java版飞机大战代码

    java版飞机大战代码 前言 Plane PlaneStatus类 Power类 Gift Diji play类 over类 MainFrame主类 MyZiDan DijiZiDan Before ...

  5. 飞机大战java_java版飞机大战实战项目详细步骤

    本文为大家分享了java版飞机大战实战项目,供大家参考,具体内容如下 分析 飞机大战 首先对这个游戏分析,在屏幕上的物体都是飞行物,我们可以把建一个类,让其他飞行物继承这个类.游戏中应有英雄机(也就是 ...

  6. python版飞机大战

    python版飞机大战 用python几百行代码搞定飞机大站游戏. 我们利用pygame包进行飞机大战的游戏开发,所以大家首先得安装好pygame包,本游戏一共封装了8个类,大家可以在GitHub上下 ...

  7. html+javascript实现的网页版飞机大战小游戏源码

    html+javascript实现的网页版飞机大战小游戏源码 完整代码下载地址: html+javascript实现的网页版飞机大战小游戏源码 index.html <!DOCTYPE html ...

  8. pygame的应用——python版飞机大战

    利用pygame实现了简易版飞机大战.源代码如下: # -*- coding:utf-8 -*- import pygame import sys from pygame.locals import ...

  9. C语言程序飞机大战,C语言版飞机大战游戏

    C语言版飞机大战,供大家参考,具体内容如下 不多说直接上代码 #include #include #include #include #include using namespace std; /*= ...

最新文章

  1. 灾难恢复级别_如何实施云计算灾难恢复
  2. 偶然发现静态函数与性能一例
  3. 算法知识点总结——算法分析基础
  4. ue linux转dos格式,uestudio中如何把dos格式转为unix
  5. CodeForces 567F DP Mausoleum
  6. ofstream写文件
  7. c语言 字符串不足用零代替,关于c语言的知识点不足的地方
  8. 山西煤炭职业技术学院计算机信息管理,山西煤炭职业技术学院计算机信息系
  9. MyBatis动态代理执行原理
  10. 系统防御工程v0.2
  11. 老域名抢注技巧是什么?
  12. 华为服务器2488H V6的ibmc接口配置
  13. 传智播客创始人张孝祥因病去世(转)
  14. IP 分类地址、子网划分你还在混淆不清吗?别怕!今天全家桶来喽
  15. Steam上不去商店和社区的方法 / SteamCommunity 443/80端口被占用报错解决办法
  16. logback 日志脱敏 隐藏PII信息
  17. 使用百度云盘快速下载文件
  18. 新媒体运营是什么??新媒体运营通过哪些方式进行?
  19. 假设检验-方差齐性检验
  20. Day82_ELK(一)

热门文章

  1. AllenBradley罗克韦尔CIP通信协议介绍 C# AllenBradley(CIP)读写操作PLC数据 C#罗克韦尔(CIP)PLC通信
  2. php算命,GitHub - baidan/efairy: 基于php的算命网站
  3. Apache 配置文件管理
  4. 读书《Python数据挖掘课程》
  5. SQL Server中字段、记录、表、列、行、属性、元组、主键、外键的含义
  6. c语言怎么定义字符串类型,求解答,在C语言里怎样定义string类型
  7. 项目实训 : Solr 使用中遇到的问题
  8. 微信小程序图片自适应高度问题
  9. 扬州市计算机职业学校名称,扬州市职业学校2019对口高考班适应性考试计算机试卷.doc...
  10. 小程序——下拉刷新,上滑更新 事件记录