android黑科技系列——爆破一款应用的签名验证问题

1、前言

在以前的文章中说过Android中的安全和破解是相辅相成的,为了防止被破解,不少应用作了一些防御策略,可是防御策略也是分等级,通常简单的策略就是混淆代码和签名校验,而对于签名校验不少应用都是会作的,通常如今就两种方式:java

第一种:签名校验不经过直接退出程序,也就是你会发现回编译二次打包运行失败的现象android

第二种:签名校验不经过不触发程序指定逻辑,致使没有错误信息,也进不了应用的现象算法

关于Android中应用防御策略的文章能够看这里:Android中应用的攻防之战 今天咱们就来看一下签名校验的应用案例,在回编译二次签名以后运行进不去游戏的问题,其实在以前已经分析过了一个签名验证的问题,那里的问题是回编译二次打包运行失败的问题。不了解的同窗能够去这里看一下:Android中使用静态方式破解apk应用;这种运行失败的应用比较好解决,由于这种签名校验的通常都在应用的入口处,因此直接在入口处加一些日志,经过打印日志就能够看到,入口通常是Application的onCreate方法和attachBaseContext方法,而经过这个案例以后咱们也学习到一个快速定位签名校验的方法的技巧:全局搜索signatures字符串,由于咱们知道若是要作签名验证,必须调用系统的一个api方法:getPackageManager().getPackageInfo(getPackageName(), 64).signatures,因此在用Jadx工具反编译apk以后,全局搜signatures字符串能够立马定位到签名校验的方法。api

2、案例分析

上面分析完了以前一个解决签名校验的案例,下面就用这个小游戏做为简单分析,这个游戏在市场均可如下载到:安全


本文研究的是V3.3版本的。咱们下载游戏以后,能够利用apktool进行反编译,而后回编译重签名,安装运行:网络


游戏能够运行成功,可是卡在这里,进不了游戏了,这时候咱们就猜测他可能有签名验证逻辑,可能放在本地,也有可能放在服务端,咱们利用上面说到的那个技巧:在Jadx中全局搜”signatures”字符串内容:工具


这时候会发现有不少地方都在使用,其实能够推断出,这个游戏为了防止二次打包在不少地方都加了签名验证的逻辑,这样对于破解也是增长必定的难度,由于这里签名校验的地方太多了,因此无法一个一个修改,因此咋们用另一种方式高效率的解决问题:在运行游戏的时候发现游戏卡在进度条了,因此猜测和网络请求有关,因此咋们就经过Fiddler抓包来分析他的请求信息:学习


游戏打开就这些请求,可是做为一个游戏不可能就这点请求的,这个也是卡住的缘由,咱们能够这么作,用一个正常的游戏在抓包看看状况:url


这个是没有二次打包签名的请求信息,和上面二次打包签名以后的请求相比较,多了不少请求,能够发现有一个get_user_info这个接口比较特殊,因此咱们能够去Jadx全局搜这个请求接口:日志


这里看到定义了url的地方,而后在全局Find Usage的地方:


点进去看方法调用:


继续查看这个方法的调用地方:


这里有四个地方调用这个方法,可是能够依次排除,最终定位到是com.wepie.snake.module.home.b.d.e()方法,那么下面来看一下如何进行排除的,能够从下往上排除,看最下面一个方法:


而后进入l.a方法中查看逻辑:


这里实际上是个请求,请求接口是d.r的值:


看到是这个接口信息,可是咱们在用Fiddler抓包的时候并无看到这个请求:


因此这个地方能够过滤了,其余三个地方的分析结果相似。因此经过这种方式定位到了方法调用的地方:


咱们在查找这个e方法调用的地方:


在这里被调用了,经过调用结果发现,有第一个判断:


这里有一个字符串比较相等的逻辑,颇有多是比较签名信息的,能够查看h.a这个方法:


这里貌似有一个字符串的构造算法,咱们为了看到最终的字符串内容,能够新建一个简单的Java项目,而后把这个方法打印一下看看结果:


看到这个最终生成的字符串内容是:678a930b9829b54a44f92a840916f7d1,而后再看一下equals的o.a的方法:


这个方法是获取应用签名信息的,而后用MD5计算结果。因此到这里咱们就知道校验签名逻辑是,获取应用的签名信息,而后MD5一下,和”678a930b9829b54a44f92a840916f7d1“字符串进行比较。那么咱们二次签名以后,这个判断确定就是false了,因此后续的逻辑就不走了,没有后面的请求,发现卡在开始界面了。

那么问题找到了,改起来就比较简单了,直接反编译游戏,而后找到这个 com.wepie.snake.helper.f.o.a()方法对应的smali代码:


把这个方法直接返回”678a930b9829b54a44f92a840916f7d1“字符串便可。有的同窗说这个怎么改?是手动编写samli代码吗?确定不是的,咋们能够先写一个简单的返回这个字符串的方法,而后反编译获得这段smali代码就能够了,可千万别本身手动的去编写,除非你有这个耐心和毅力,反正我没有。替换完成以后,咋们就回编译,二次签名运行安装游戏,惋惜的是仍是卡住了,因此还得回去看代码:


咋们修改了一次签名校验方法,进入了第一层签名判断,继续往下看代码:


这里又有一个判断,点进去查看逻辑:


果真,这里又有了一次签名校验方法,因此还得手动的修改,修改方法和上面相似,把这个p方法改一下便可:


修改为功以后,再次回编译重签名安装运行,惋惜的是仍是卡住了,进不了游戏,这时候咱们在次抓包看看:


此次比以前多了一个config_v3_android请求,可是仍是没有get_user_info的请求!因此还得去看代码逻辑,不过从请求结果来看,咱们以前的两次签名校验修改已经有效果了,继续看下面的代码:


这里能够看到,有一个设置进度条的逻辑,并且有一个tag=999的日志,貌似是取配置信息的进度条,那么咱们能够查看这个日志信息:


看到了这个日志信息以后,发现有开始取config到获取成功config了,可是后面就没有日志了,因此这里猜测应该是在本地解析这个配置信息的时候还有判断,咋们全局搜一个字符串信息”getConfigAndroid“:


第一条信息就是咱们想要的,点击进入:


果真这里还有一个判断,进入查看:


又是一次签名校验的逻辑,好吧,还得再一次改这个com.wepie.snake.helper.b.a.i()方法了:


修改为功以后,再次回编译二次签名安装运行便可,此次终于运行成功,进入游戏界面了。

3、签名校验破解方案

好了,到这里咱们来总结一下关于如何解决应用二次签名校验的问题:

第一步:先在Jadx中打开应用以后,全局搜字符串内容:”signatures”,这个就能够定位到获取应用签名信息的地方了,而后能够依次跟踪校验的地方了。

第二步:在第一步搜索结果比较多的状况下,咱们能够经过应用运行效果采用这两种方式:

  • 第一种方式:若是应用运行失败,那么多是在应用入口处做了签名校验逻辑,若是校验失败就退出程序。通常入口处是在Application的onCreate方法和attachBaseContext方法。
  • 第二种方式:若是应用能够运行,可是卡在某一个地方,咱们能够采用抓包技术来分析应用运行到哪一步卡住了,由于如今的应用都会有请求的,若是是卡住了,那么请求就会和原始包的请求不一样,能够根据不一样的请求结果来跟踪代码逻辑,就好比本文的案例。

上面就是本人总结的签名校验的大体解决步骤和方法,可是确定还有其余场景,好比有的应用会把签名放到native层,可是这些校验逻辑都是能够作处理的,也有的应用把签名信息放到服务端进行校验,这个也是能够处理的。放在native层的话,最终也是经过java层作链接访问的,只要到了java层,那么就能够找到校验方法的地方,放在服务端校验,仍是能够经过抓包查看请求来解决的。

4、签名校验破解后续

从上面看其实在给应用作防御的时候,签名校验这种方式不是百分百的安全,只能防止一些破解小白。其实本文的案例中能够发现,这个应用其实想经过多个地方的签名校验来作到全局校验,本文中能够看到咱们作了三次的签名校验方法代码修改才成功的,并且后续版本也不排除他们还会继续增长,以及在其余地方逻辑处也作了签名校验判断。

从本文中也能够看到若是一个应用在不少地方都作了签名校验,那么咱们手动修改会显得很麻烦,其实这里有这个思路:获取应用的签名方法是固定的:getPackageManager().getPackageInfo(getPackageName(), 64).signatures,咱们能够直接修改应用的Application信息,经过反射机制,把校验对象的字符串内容设置到signatures中,说白了就是用反射来修改应用的签名信息,这样在应用中全部获取签名的地方都是咱们设置的指定签名值,也就是比对的那个常量字符串内容,全部的签名校验方法都是返回true了。这个思路本文再也不尝试了,感兴趣的同窗能够尝试。就是一个反射调用便可。有的同窗可能在想怎么不用Xposed进行hook应用的签名获取方法那样不就更简单了。这里必定要注意呀,咱们为何要解决签名校验,就是由于咱们想二次签名打包,而Xposed进行hook的时候是不须要二次打包的,主要hook点找到,不用进行二次打包安装就能够实现破解了。这两种方式思路是不一样的,要注意哈!

5、给应用安全防御的意见

经过本文案例,其实对于如今应用防御有这些建议:首先关于应用签名校验这块逻辑,能够作的更安全点,就是在native层用反射调用系统获取签名的方法,而后直接在native层进行比较,若是发现签名不正确,就退出程序,所有放在native层作,这样安全系数会高点!

可是这种也不是最安全的,安全点也就是考虑加固方案了,如今加固平台不少,选择企业版加固,对于破解难度那是确定会加大的。可是加固有一个弊端,就是崩溃率的问题,由于了解加固原理的同窗都知道,如今加固平台都会涉及到so逻辑,而Android由于机型和系统版本复杂,致使兼容性很差,会有必定的加固崩溃率的,而对于一些用户量比较多的应用和游戏,他们没法忍受这种崩溃率,那么就放弃加固了。可是加固仍是一个相对安全的策略!

严重声明:本文的目的只有一个,经过一个案例来分析如今应用的签名校验逻辑,如何破解这种校验方式,若是有人利用本文内容进行任何商业目的和非法牟利,带来的任何法律责任将由操做者本人承担,和本文做者没有任何关系,因此仍是由衷的但愿你们秉着技术学习的目的阅读此文,很是感谢!

6、总结

本文经过一个案例分析了应用签名信息校验的防御策略破解,最后也总结了如今这种签名校验防御策略的弊端和改进的地方,如何作到安全系数比较高的防御。可是也不是最安全的,由于没有绝对的安全!安全和逆向是相互进步!共同促进社会进步和技术革新!

相关文章
相关标签/搜索