Android逆向之旅---爆破应用签名的一种全新高效方式(Native+服务器验证)

一、知识回顾
关于Android中的签名校验是一种很普遍的安全防护策略了,很多应用也都做了这部分的工作,在之前我也介绍了几篇关于如何爆破应用的签名校验问题的文章,不了解的同学可以去查看:Android中爆破应用签名校验功能,当时介绍完这篇文章之后,其实总结了现在爆破签名校验的几种方式,其中最方便快捷的就是:全局搜索字符串内容:“signature”,因为只要有签名校验功能,一定会调用系统的一个方法,而这个方法中就是包含了这个字符串内容。

之前的这篇文章中介绍的签名校验处理方式也是如此,找到具体签名校验功能之后,直接替换正确的签名信息就可,或者把if判断手动改成true也可以。但是当时说到一个问题,就是现在应用为了加强防护,几乎在重要的内容部分中都加了签名校验功能,所以如果要手动的改,就需要把每个签名校验的地方都得改一下,这样会显得很费劲,有的人说了,有一个好的办法,就是用Xposed来hook这个应用的获取系统签名的方法,然后替换方法的返回值即可。这种方式是可以的,但是不是最好的,因为如果你解决了签名校验,二次打包给别人用,不可能叫人家还root手机,然后在装Xposed框架功,是不合理的。所以我们需要从根本上解决这个问题,也是本文介绍的一个重点。后面会介绍一种万能的高效方法。

之前的文章中我们可以看到,大部分签名校验都是在Java层,本地做的校验。所以爆破难度不是很大,而今天我们要介绍的一个应用样本他的签名校验是放在so中,而且结合了服务端进行验证,难度加大。不过万变不离其宗,签名校验永远都是需要获取应用本身的签名信息,进行比对操作的。

二、爆破签名校验
下面就开始进入本文的主题,看一下应用样本的签名校验问题,拿到样本之后,直接反编译,二次打包,安装出现如下错误信息提示:


这个直接弹出对话框信息,点击确定就退出程序了,这个比较简单,反编译之后,通过提示内容,找到签名校验入口,在values/string.xml中找到这个字符串信息即可:

然后用Jadx打开这个应用,全局搜索这个name值:

点击进入代码位置即可:

看到i方法中有一个show方法,应该就是对话框展示的逻辑。看看这个i方法调用的地方:

看到了,在之前有一个判断,如果为false,就是走到i方法,展示对话框,所以这个checkHashKey方法肯定是签名校验的方法,进入查看:

是个native方法,全局搜SocketJNI类调用的地方:

在这里看到会加载一个so文件,也就是libmzd.so文件,我们用IDA打开这个文件(文件在反编译之后的libs目录下):

找到对应的native函数,查看具体逻辑代码:

为了更好的阅读代码,使用F5,查看对应的C语言代码,这里的逻辑非常简单,就是把Java层传递的签名字符串内容,在做一次MD5值,然后和指定的字符串"8f2a24...."作比对即可。那么上面传入到的checkHashKey方法的值是通过com.xiaoenai.app.utils.aj.m方法:

这里看到就是标准的获取应用签名信息的方法。

到这里就看到了一个Java层的签名校验方法,这里解决这个问题有很多种方法,可以修改对应的smali方法,把if判断强制改成true即可。还可以直接修改m方法的返回值为正确的签名字符串内容。这里选择第二种,因为我们需要引用的签名字符串内容,后面会继续用到。这个获取方法也很简单,直接写一个Demo案例,通过应用包名构建出对应的Context变量,然后就开始获取签名信息即可:


运行这个demo程序,前提是你的设备中要安装一个官方版本的应用,这样才能获取到正确的签名字符串内容:

看到了,其中签名字符串:"aN+VCd8ns0yqsotX2WuKyScq/ZA=" 就是正确的官方版本的值。下面在顺便写一个直接返回这个字符串的方法,然后变编译得到对应的smali代码:

然后把这个方法的的代码拷贝替换样本应用的aj.m方法代码即可:

保存,二次打包即可,记住:这里没必要手动的编写smali代码返回指定的签名字符串,除非你对smali语法非常熟悉了,不过我是不会这么做的。因为我不熟悉smali,最笨的最有效的方法就是自己手动写一个Java方法,然后反编译得到对应的smali代码即可。
二次打包成功之后,安装应用,运行发现竟然还有错误,登录失败:

这时候,就想到了,样本应用可能做了服务端数据验证,下面就来看看如何解决这个问题,这个问题的突破口比较简单,不要在用提示字符串信息去找了,因为这错误信息可能是服务端返回的,这时候就需要借助抓包了,每次请求一次,就抓一次服务包,这里用了Fiddler工具:

这里看到,请求的参数非常简单,一个加密之后的数据data和版本号ver,返回的数据提示加密签名错误,所以我们可以在Jadx中全局搜"login2"字符串信息,找到突破口:

找到之后,双击进入代码:

看到最终调用了,a方法,点击进入a方法:

这里会通过一个过程构造出一个json参数格式,继续往下看:

携带了这些信息参数值,为了更好的看到这个json数据格式,我们可以利用Xposed下一个hook功能:

然后运行这个Xposed模块,在点击样本的登录功能,查看日志信息:

看到了,result就是最终拼接好的json参数格式内容。其中最后一个字符串sig是将签名整个参数做一次加密操作,为了在服务端校验参数的完整性。得到这个json格式之后,会调用com.xiaoenai.app.utils.b.a.a方法:

继续查看这个方法实现:

继续跟踪代码:

又是到了native方法了,到这里其实上次Java将拼接好的参数信息以json格式传递到native层进行加密操作,继续看native层代码实现,依然在之前的那个libmzd.so中:

找到对应的核心函数功能,跟踪查看实现:

继续跟踪:

这里看到了,有data字符串内容了,也就是这里开始对上面传递的json数据进行加密,然后拼接到data中,在native层在拼接一套json:{"data":"加密之后的值", "ver":"1.1"},而在这里有一个寻找加密key的函数,可惜这里我不在分析了,因为我看的头疼,他的加密算法还是比较复杂的。所以就放弃分析了。
那么到这里,我们有什么方式可以得到加密算法呢?有的同学可能想到了动态调试,这个方法是最好的,但是这个app做了很多反调试策略,动态调试也是不好弄的,而且这个算法有点复杂,及时动态调试,也要详细阅读arm指令,才能猜到这个加密算法功能。所以这条路不好走。
那么还有其他方法了?当然有,就是文章开头说到的一句解决签名校验的基本法则:全局搜索字符串"signature";在IDA中也是如此,使用Shirt+F12打开so中的字符串窗口,然后搜索signature

果然找到了,双击进入:
Android逆向之旅---爆破应用签名的一种全新高效方式(Native+服务器验证)
看到这里可能是在native层调用了系统获取签名的方法,选中红色框中的内容,然后按X键,展示被调用的地方索引

双击进入,这个就是我们之前分析的那个SocketJNI的init方法:

到这里,为了更好的阅读代码,需要把这个函数地址改成可读,也就是JNIEnv即可,选中红色框,按下Y键即可

修改成JNIEnv
,确定即可:

这样就看的比较清楚了,而这部分代码也非常简单,就是调用系统获取签名的方法,然后赋值到一个变量中,不过这里获取的不是字符串内容,而是int类型的hashCode值:

在返回到arm代码处,看到赋值,就是将R0寄存器值搞到R9中去。

到这里,我们一定要思路清楚,就是不管native层怎么加密,最终会利用应用的签名值来做加密的key信息。所以我们只要解决掉获取签名信息值即可,也就是这里的R9寄存器值,我们还需要再一次去获取正版的签名信息的hashCode值即可:



然后运行,查看值:-2081383250



然后我们可以修改上面的arm指令:MOV R9,R0;不过这里还不好弄,因为这个hashCode值int类型四个字节,而这里看到一个命令才2个字节,肯定不够用。需要借助LDR伪指令来进行操作了。但是这里不做这么费劲的修改了。因为假如其他地方也有这样的功代码,那么还得去修改,就是回到了我们文章开始说到的那个问题,要解决所有的签名校验功能,才是本文的目的。

不过到这里,我们可以先这么尝试检验我们的爆破结果,就是借助Xposed框架,hook这个应用获取签名的hashCode方法,将返回值替换成正确的-2081383250值:



修改之后,运行:



果然成功了,而且对于之前的去除对话框那个逻辑也可以不用那么麻烦了,这么一来整个app所有的签名校验地方都是爆破了。不过这种方式利用的是Xposed,所以不是最终方案。下面就来介绍一种高新技术来解决这个问题。

三、高效的Hook爆破方式
不知道大家是否还记得我之前介绍过一个系统篇系列文章,介绍如何Hook系统的各个服务,比如AMS,PMS等功能,然后在应用内进行拦截activity启动的功能。不了解的同学可以看这篇文章:Android中Hook系统服务功能;原理非常简单就是利用反射机制+动态代理技术,替换系统服务的Binder对象即可。这个技术好处是免root操作,缺点是只能在应用内部进行操作使用。那有的人好奇了,既然只能在应用本身内部有效,那有什么用呀?其实不然,现在有些开发场景就需要这个技术,及时现在没用到,将来也不一定,这不在这里就用到了。下面我们就用这个技术来Hook系统的PMS服务,拦截应用获取签名信息的方法。因为只要在本应用中操作,所以正好符合要求。
操作步骤很简单,我们在样本应用启动的入口处,加上我们的拦截代码即可,那么下面我们先把拦截PMS服务代码写好,这个代码下载地址文章末尾给出。


就是利用反射去hook系统的类,然后用动态代理构造一个自己的PMS Binder进行替换即可:

在这里我们可以通过方法名来拦截签名信息,我们用正版的签名信息构造一个新的Signature对象,然后将其设置已有的对象中即可。因为我们最终还是需要把代码放到样本案例的入口处,所以就在这里将这两个类放到样本入口类的包下面,具体包名可以手动构造:

然后将这个demo反编译,得到对应的smali代码,拷贝到样本案例对应的包下面,然后在样本案例的入口处加上方法调用:ServiceManagerWraper.hookPMS(this); 对应的smali代码如下:
invoke-static {p0}, Lcom/xiaoenai/app/ServiceManagerWraper;->hookPMS(Landroid/content/Context;)V
样本入口可以从AndroidManifest.xml中的application找到


在Application的onCreate方法入口添加即可,添加完成之后,二次打包,再次使用Jadx打开修改之后的apk包:

入口处代码已经添加完毕了。然后安装运行,就可以完成。而这么操作之后应用所有的签名信息就是正确的。包括native层的签名校验逻辑。所以这种方式是最靠谱的。不要改多处签名校验的逻辑了。

四、签名校验爆破方式总结
到这里我们就成功的爆破了一款服务端+Native双签名校验的样本案例了,而这次操作签名爆破之后,后面将不会在介绍更多的签名校验了,原因很简单,因为这次操作之后,我们发明了一个通用的爆破方式,可以解决签名校验问题了,下面就来总结一下现阶段Android中签名校验逻辑处理方式:
第一、基本法则不能忘:全局搜索字符串"signature",Java层可以用Jadx进行搜索,so中可以用IDA进行搜索。
第二、在逆向领域中,字符串信息永远是第一选择的爆破的突破口,在之前的文章我已经多次讲到了,不管是IDA,还是Jadx工具,只要全局搜索关键字符串信息,就可以找到我们想要的入口。
第三、本文的重点:发明了一种全新的高效的爆破应用签名校验逻辑,就是可以手动Hook样本应用的PMS功能,然后在应用的入口处加上hook代码。最终在hook的invoke方法中拦截想要的方法即可。
有了本文的思路,后面会开发一个工具,一键式解决签名问题,原理就是利用我之前介绍的 icodetools工具 和本文介绍的hook系统PMS服务,篡改应用签名信息。关于具体细节和工具开发敬请期待。如果此工具开发完成,那么对于签名校验的应用绝对是一个新的挑战。安全不息,逆向不止!

严重声明:****本文的目的只有一个,通过一个案例来分析现在应用逆向分析技巧,如果有人利用本文内容进行任何商业目的和非法牟利,带来的任何法律责任将由操作者本人承担,和本文作者没有任何关系,所以还是由衷的希望大家秉着技术学习的目的阅读此文,非常感谢!

Hook代码下载地址:https://github.com/fourbrother/HookPmsSignature

五、总结
本文介绍的内容稍微有点多,所以大家看的可能有点累,其实还有一部分内容没介绍,就是如何访问已有的so文件中的函数,变量值,这个是我在这个样本案例中用到的一个方法,限于篇幅原因就不多介绍了。但是一定要记住本文的最后一种爆破签名校验方式的方法。此等绝对高级正能量。希望可以言传。最后看完文章,如果觉得有收获,就多多点赞扩散分享,如果有打赏那就最好啦啦!!

更多内容:点击这里

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


编码美丽技术圈
微信扫一扫进入我的"技术圈"世界

扫一扫加小编微信添加时请注明:“编码美丽”非常感谢!


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容