• Android逆向之旅---带你爆破一款应用的签名验证问题


    一、前言

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

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

    另外一种:签名校验不通过不触发程序指定逻辑,导致没有错误信息。也进不了应用的现象

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


    二、案例分析

    上面分析完了之前一个解决签名校验的案例,以下就用这个小游戏作为简单分析,这个游戏在市场都能够下载到:


    本文研究的是V3.3版本号的。我们下载游戏之后,能够利用apktool进行反编译。然后回编译重签名,安装执行:


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


    这时候会发现有非常多地方都在使用,事实上能够推断出,这个游戏为了防止二次打包在非常多地方都加了签名验证的逻辑。这样对于破解也是添加一定的难度,由于这里签名校验的地方太多了,所以没法一个一个改动,所以咋们用另外一种方式高效率的解决这个问题:在执行游戏的时候发现游戏卡在进度条了。所以猜想和网络请求有关,所以咋们就通过Fiddler抓包来分析他的请求信息:


    游戏打开就这些请求,可是作为一个游戏不可能就这点请求的。这个也是卡住的原因,我们能够这么做。用一个正常的游戏在抓包看看情况:


    这个是没有二次打包签名的请求信息,和上面二次打包签名之后的请求相比較,多了非常多请求,能够发现有一个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()方法了:


    改动成功之后,再次回编译二次签名安装执行就可以。这次终于执行成功。进入游戏界面了。


    三、签名校验破解方案

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

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

    第二步:在第一步搜索结果比較多的情况下。我们能够通过应用执行效果採用这两种方式:

    • 第一种方式:假设应用执行失败,那么可能是在应用入口处作了签名校验逻辑,假设校验失败就退出程序。一般入口处是在Application的onCreate方法和attachBaseContext方法。
    • 另外一种方式:假设应用能够执行,可是卡在某一个地方。我们能够採用抓包技术来分析应用执行到哪一步卡住了,由于如今的应用都会有请求的,假设是卡住了。那么请求就会和原始包的请求不同,能够依据不同的请求结果来跟踪代码逻辑。就比方本文的案例。

    上面就是本人总结的签名校验的大致解决步骤和方法。可是肯定还有其它场景,比方有的应用会把签名放到native层。可是这些校验逻辑都是能够做处理的,也有的应用把签名信息放到服务端进行校验。这个也是能够处理的。

    放在native层的话,终于也是通过java层做连接訪问的。仅仅要到了java层。那么就能够找到校验方法的地方,放在服务端校验。还是能够通过抓包查看请求来解决的。


    四、签名校验破解兴许

    从上面看事实上在给应用做防护的时候,签名校验这样的方式不是百分百的安全。仅仅能防止一些破解小白。事实上本文的案例中能够发现,这个应用事实上想通过多个地方的签名校验来做到全局校验。本文中能够看到我们做了三次的签名校验方法代码改动才成功的,并且兴许版本号也不排除他们还会继续添加,以及在其它地方逻辑处也做了签名校验推断

    从本文中也能够看到假设一个应用在非常多地方都做了签名校验,那么我们手动改动会显得非常麻烦。事实上这里有这个思路:获取应用的签名方法是固定的:getPackageManager().getPackageInfo(getPackageName(), 64).signatures,我们能够直接改动应用的Application信息,通过反射机制,把校验对象的字符串内容设置到signatures中,说白了就是用反射来改动应用的签名信息,这样在应用中全部获取签名的地方都是我们设置的指定签名值,也就是比对的那个常量字符串内容,全部的签名校验方法都是返回true了

    这个思路本文不再尝试了,感兴趣的同学能够尝试。就是一个反射调用就可以。

    有的同学可能在想怎么不用Xposed进行hook应用的签名获取方法那样不就更简单了。这里一定要注意呀。我们为什么要解决签名校验,就是由于我们想二次签名打包,而Xposed进行hook的时候是不须要二次打包的,主要hook点找到。不用进行二次打包安装就能够实现破解了。

    这两种方式思路是不同的,要注意哈。


    五、给应用安全防护的意见

    通过本文案例,事实上对于如今应用防护有这些建议:首先关于应用签名校验这块逻辑,能够做的更安全点。就是在native层用反射调用系统获取签名的方法,然后直接在native层进行比較,假设发现签名不对,就退出程序,全部放在native层做,这样安全系数会高点!

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


    严重声明:本文的目的仅仅有一个,通过一个案例来分析如今应用的签名校验逻辑,怎样破解这样的校验方式,假设有人利用本文内容进行不论什么商业目的和非法牟利。带来的不论什么法律责任将由操作者本人承担,和本文作者没有不论什么关系,所以还是由衷的希望大家秉着技术学习的目的阅读此文,非常感谢!


    六、总结

    本文通过一个案例分析了应用签名信息校验的防护策略破解,最后也总结了如今这样的签名校验防护策略的弊端和改进的地方。怎样做到安全系数比較高的防护。可是也不是最安全的,由于没有绝对的安全!

    安全和逆向是相互进步!

    共同促进社会进步和技术革新!最后要是阅读完本文内容认为有收获就点个赞多多分享。要是有打赏那就最好了啦!

    很多其它内容:点击这里

    关注微信公众号,最新技术干货实时推送

    扫一扫加小编微信
    加入时请注明:“编码漂亮”非常感谢!

  • 相关阅读:
    Java8学习笔记(五)--Stream API详解[转]
    Java8学习笔记(四)--接口增强
    Java8学习笔记(三)--方法引入
    JAVA8学习笔记(二)----三个预定义接口
    JAVA8学习笔记(一)----Lambda表达式
    Java基础加强总结(三)——代理(Proxy)
    Java基础加强总结(二)——泛型
    mysql统计表的大小
    jquery异步上传图片
    瀑布流
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7353788.html
Copyright © 2020-2023  润新知