转52破解jiangwei212Android爆破应用签名的一种全新高效方式(Native+服务器验证)

本文主要是介绍转52破解jiangwei212Android爆破应用签名的一种全新高效方式(Native+服务器验证),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:Android爆破应用签名的一种全新高效方式(Native+服务器验证)

http://www.52pojie.cn/thread-606272-1-1.html

(出处: 吾爱破解论坛)

 

AndroidAndroid中爆破应用签名校验功能Java一、知识回顾关于中的签名校验是一种很普遍的安全防护策略了,很多应用也都做了这部分的工作,在之前我也介绍了几篇关于如何爆破应用的签名校验问题的文章,不了解的同学可以去查看:,当时介绍完这篇文章之后,其实总结了现在爆破签名校验的几种方式,其中最方便快捷的就是:全局搜索字符串内容:"signature",因为只要有签名校验功能,一定会调用系统的一个方法,而这个方法中就是包含了这个字符串内容。之前的这篇文章中介绍的签名校验处理方式也是如此,找到具体签名校验功能之后,直接替换正确的签名信息就可,或者把if判断手动改成true也可以。但是当时说到一个问题,就是现在应用为了加强防护,几乎在重要的内容部分中都加了签名校验功能,所以如果要手动的改,就需要把每个签名校验的地方都得改一下,这样会显得很费劲,有的人说了,有一个好的办法,就是用Xposed来hook这个应用的获取系统签名的方法,然后替换方法的返回值即可。这种方式是可以的,但是不是最好的,因为如果你解决了签名校验,二次打包给别人用,不可能叫人家还root手机,然后在装Xposed框架功,是不合理的。所以我们需要从根本上解决这个问题,也是本文介绍的一个重点。后面会介绍一种万能的高效方法。之前的文章中我们可以看到,大部分签名校验都是在层,本地做的校验。所以爆破难度不是很大,而今天我们要介绍的一个应用样本他的签名校验是放在so中,而且结合了服务端进行验证,难度加大。不过万变不离其宗,签名校验永远都是需要获取应用本身的签名信息,进行比对操作的。

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

 

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

 

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

 

点击进入代码位置即可:

 

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

 

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

 

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

 

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

 

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

 

C语言为了更好的阅读代码,使用F5,查看对应的代码,这里的逻辑非常简单,就是把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

 

果然找到了,双击进入:

 

看到这里可能是在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,所以不是最终方案。下面就来介绍一种高新技术来解决这个问题。

Android中Hook系统服务功能三、高效的Hook爆破方式不知道大家是否还记得我之前介绍过一个系统篇系列文章,介绍如何Hook系统的各个服务,比如AMS,PMS等功能,然后在应用内进行拦截activity启动的功能。不了解的同学可以看这篇文章:;原理非常简单就是利用反射机制+动态代{过}{滤}理技术,替换系统服务的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层的签名校验逻辑。所以这种方式是最靠谱的。不要改多处签名校验的逻辑了。

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

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

 

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

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

这篇关于转52破解jiangwei212Android爆破应用签名的一种全新高效方式(Native+服务器验证)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1025656

相关文章

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

Debian系和Redhat系防火墙配置方式

《Debian系和Redhat系防火墙配置方式》文章对比了Debian系UFW和Redhat系Firewalld防火墙的安装、启用禁用、端口管理、规则查看及注意事项,强调SSH端口需开放、规则持久化,... 目录Debian系UFW防火墙1. 安装2. 启用与禁用3. 基本命令4. 注意事项5. 示例配置R

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件