Android逆向【4】:暴力破解APK签名校验,愉快的重新打包微信支付宝APK

2023-05-16

回顾

《Android逆向小技巧③:批量注入日志,打印目标程序执行流程》

在上一篇2019年的文章中,我们使用python写了一个简单的文本处理工具:
https://github.com/encoderlee/android_tools

在使用apktool对目标应用的apk解包以后,用这个python写的小工具,分析反编译出来的smali代码,并在每个方法中注入日志,然后对apk重新打包,这样,但APP运行的时候,我们每做一个操作,都可以从日志中看出目标代码的执行流程。

不过这种方式有一个很大的缺点,就是现在很多APP都做了签名校验,重新打包后,APP启动时检查到自身签名不对,发现自己被重新打包了,就罢工不再工作了。

签名校验

以支付宝目前的最新版10.2.50 (2021-12-20) 为例,使用apktool重新打包后,你需要使用apksigner重新签名才能安装:

apksigner sign --v2-signing-enabled false --v3-signing-enabled false --ks encoderlee.jks alipay.apk

但是重新签名签的这个名,只能用自己生成的证书去签名,因为你不可能搞到支付宝的证书和私钥。

这个时候如果直接安装运行这个APK,会出现这样的问题:

在这里插入图片描述
抱歉,请求参数不合法。

其实这就是因为APP检测到自身签名不对,就拒绝服务的表现,有的APP会表现为闪退。
其实想想也很容易理解,apktool解包,修改,重新打包APP那么简单,没有哪个厂商愿意让自己的APP被随意的玩弄和修改,所以目前绝大多数的APP都做了签名校验。

常规对抗

常规的对抗思路是,既然你在代码中做了签名校验,那么我找到你校验签名的代码,通过修改smali文件或用Xposed干掉它,不久OK了。于是你在网上可以搜到很多如何校验签名的代码:

 public static int verifySignature(Context context) {
        boolean isValidated  = false;
        try {
            //得到签名
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(),PackageManager.GET_SIGNATURES);
            Signature[] signs = packageInfo.signatures;

            //将签名文件MD5编码一下
            String signStr = md5(signs[0].toCharsString());

            //将应用现在的签名MD5值和我们正确的MD5值对比
            return signStr.equals("这里写正确的签名的MD5加密后的字符串");
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return isValidated;
    }

本质上来说这些签名校验的代码,都是调用 PackageManager.getPackageInfo().signatures 去获取自身的签名信息,进行比较判断自己是否被重新打包。

实际上,你在微信和支付宝反编译出的代码中,也能找到这些调用,但当你尝试修改smali或用xposed干掉这些调用的,替换原版的 signatures 数据,就会发现:

并没有什么卵用

想想也不可能那么简单,微信支付宝可是和这帮打包者对抗多年了,实际上在微信支付宝中,还使用了多种手段来校验自身签名,其中就包括在so中使用本机代码来实现校验,这样使得我们解决起来非常麻烦。

当然理论上来说,你完全可以找到它在so中检验签名的代码,干掉它,但是时间成本未免太高,看看微信支付宝的那个JAVA代码量,以及so的数量,想在这些海量代码中分析出关键点来,非常麻烦,就不要在这个思路上浪费时间了。

剑走偏锋

那么,能不能找到一种通用的办法,干掉大多数APP的签名校验呢?

我们先来分析,apksigner对APK签名,本质上是做了什么事情?

我们可以比较apktool重打包后没有签名的APK文件和apksigner签名后的APK文件,发现在APK文件中多了一个【META-INF】目录,里面的文件保存的实际上就是签名和文件校验信息。

Android签名原理可以看这篇文章:《Android 端 V1/V2/V3 签名的原理》

而PackageManager.getPackageInfo().signatures获取的signatures是什么?实际上就来自【META-INF】目录中的【CERT.RSA】文件(有的APK里面的RSA文件不一定是这个名字,但都以.RSA结尾),里面有【包含公钥的开发者证书】,证明这个APK是谁签名的。

那么,我们直接把原版APK中的【META-INF】目录下的【CERT.RSA】取出来,覆盖到我们打包后的APK中,不就可以了?这样APK运行后,获取到的signatures 仍然是支付宝自己原版的 signatures 。

理想是美好的,但是Android的这套签名机制当然不会那么傻,这样简单替换【CERT.RSA】文件后的APK,自然是无法正常安装的,提示【INSTALL_PARSE_FAILED_NO_CERTIFICATES】错误,这是因为【CERT.RSA】不仅包含【开发者证书】也包含【对 CERT.SF 文件的签名】,我们重新打包APK后,【MANIFEST.MF】和【CERT.SF】都改变了,自然支付宝原版的签名就和它对不上了,android系统在安装的时候检测到签名对不上,自然就不允许安装。

但要知道,Android系统是开源的,我们能不能修改Android系统源代码,让它允许安装签名错误的APK呢?当然是可以的。实际上也不需要这么麻烦,如果我们有root权限或有xposed,一样可以Hook Android系统本身的代码,让Android系统跳过签名校验,安装这个签名错误的APK。

这样的Xposed模块早已有人写好了,就是【幸运破解器「Lucky Patcher」】

https://www.luckypatchers.com/download/

幸运破解器有两种方式来运行,一种是手机已经Root,一种是手机已装好Xposed。

推荐Xposed的方式来运行,装好幸运破解器后,在Xposed中勾选启用该模块,打开幸运破解器APP。

【工具箱】-》【Android核心破解】-》勾选【签名验证始终真实】,勾选【禁用ZIP签名验证】
在这里插入图片描述
一番操作后,我们就可以把重新打包后签名不对的APK安装到这个手机上。即使APP运行起来后,动态检查签名,也不会有什么问题,因为无论在JAVA层还是so层获取signatures,最终都是从【CERT.RSA】读取的数据,而【CERT.RSA】已经被我们替换成了支付宝原版的【CERT.RSA】,货真价实,APP运行起来后动态检测也不会发现什么异常,于是我们就可以正常运行我们重新打包修改过的微信支付宝APP了,当然其它大多数APP都可以这样来搞。

注意!这种覆盖【CERT.RSA】文件的方法,仅仅适用于V1签名,所以我们上面使用

apksigner sign --v2-signing-enabled false --v3-signing-enabled false --ks encoderlee.jks alipay.apk

给APK前面的时候,禁用了V2 V3签名,只保留V1签名

(也许V2 V3也有对应的搞法?回头有空再研究)

神器【VirtualXposed】

有人说,这种方式也太苛刻了吧,这样一搞,虽然是个通用和万能的方法破解了签名校验,但是要求安装该APP的手机,必须是一个ROOT过的手机,或者装了Xposed的手机呀,现在最新的小米华为手里,想要ROOT和Xposed,实在太麻烦了。而且我修改过的APP,想发布到群里给大家伙使用,不可能大家伙都要去ROOT手机吧?

那就要借助大名鼎鼎的 【VirtualXposed】了!
https://github.com/android-hacker/VirtualXposed

这个神器,可以在没有Root权限的手机上创建一个虚拟环境,然后对该虚拟环境内的APP启用Xposed模块!
这个项目的作者真的是个天才,这个思路都被他想出来并且付诸实现了。

而且 【VirtualXposed】本身实际上已经集成了【幸运破解器「Lucky Patcher」】的【Android核心破解】功能,即允许在【VirtualXposed】中安装签名不对的APK。

在这里插入图片描述
我们只需要在【VirtualXposed】的【高级设置】中勾选【允许安装没有签名的应用】
这样就不需要【幸运破解器「Lucky Patcher」】了,绝大多数APK,我们使用apktool重新修改打包后,只需把原APK的签名文件【CERT.RSA】覆盖回去,然后通过这样的方式,安装签名不对的APK文件,就可以暴力绕过APK签名校验,愉快的重新打包和分发各种APP了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android逆向【4】:暴力破解APK签名校验,愉快的重新打包微信支付宝APK 的相关文章

  • Linux桌面菜单(.menu)规范

    Version 1 1 xff0c 最新版 20 August 2016 文章目录 介绍文件位置 desktop文件的扩展使用Categories和OnlyShowIn的例子 菜单文件的格式文件类型声明元素 示例菜单文件A 注册类别主要类别
  • Flask+python 爬虫制作股票查询、历史数据、股评词云网页

    自学python的数据分析 xff0c 爬虫后 xff0c 花了几天时间学习Flask做了一个简单的股票查询网页 本想着加入其它的分析板块 xff0c 不过发现部署到服务器还要花钱 xff0c 于是先到此为止 xff0c 后面可能会继续加入
  • 关于部分网页打不开的解决方法详解

    我们上网时可能出现症状 xff1a 部分网页可以打开 xff0c 有些网页或者二级网页打不开 xff0c 或者是网页可以打开但是网页却不能正常显示 xff08 如图片加载失败 xff0c 不能显示网页底色 xff09 xff0c 出现如下的
  • 部署linux服务器上后https接口请求抛异常javax.net.ssl.SSLHandshakeException

    接口中用到https的URL请求服务 xff0c 本地测试正常 部署到linux服务器上后 xff0c 请求调不通 xff0c 抛出了如下异常 xff0c 截取了片段 xff1a javax net ssl SSLHandshakeExce
  • Royal TSX Terminal 通过ssh 无法连接阿里云服务器

    第一次使用Royal TSX 连接阿里云服务器顺利连接 xff0c 成功 然而我重置了阿里云服务器实例 xff0c 再次连接不行了 xff0c 可以ping通 xff0c 没有问题 xff0c 那问题在哪儿呢 xff0c 折腾了好长时间 x
  • zynq7020 vxWorks 移植问题笔记:bootrom启动时间过长

    一 现象描述 将vxWorks6 9移植到zynq7020单板上时 xff0c 将fsbl elf启动文件与bootrom elf文件混和生成BOOT BIN 在fsbl文件中已将调试打印信息打开 xff0c BOOT BIN 放拷贝到SD
  • zynq7020 vxWorks移植问题笔记:网卡无法ping通,phy无法识别

    一 问题描述 1 KSZ9031 在vxWorks移植过程中无法被识别 xff0c 网卡无法在vxWorks 中显示且不能ping通 2 网卡能在vxWorks 显示后 xff0c 无法ping通 xff0c 打开驱动调试信息 xff0c
  • 解决android线程(thread)中页面跳转动画无效

    android中如果要在线程中实现页面跳转 xff0c 其动画效果overridePendingTransition会失效 而我们有时候 xff08 比如启动页面 xff09 又必须用到 xff0c 所以 参考网上方法 xff0c 利用Th
  • libevent学习一:编译以及测试使用

    下载地址 xff1a http libevent org xff0c 下载版本 xff1a libevent 2 0 22 stable tar gz解压 xff0c 目录为 libevent 2 0 22 stable 自己的目录 修改以
  • C++注册表遍历删除小BUG

    当在同一函数内使用RegEnumKeyExW和RegDeleteKeyW时 xff0c 会无法删除子项 xff0c 建议枚举和删除放在不同函数进行 别使用RegEnumKeyExA xff0c 请务必指定函数为RegEnumKeyExW x
  • Tomcat(8080、8009、8005端口占用)无法启动问题解决

    在spring框架中 xff0c 随着spring项目运行 xff0c 会把tomcat给启动 xff0c 其实tomcat已经启动 解决办法 xff1a 将tomcat服务设置为手动
  • Slf4j、log4j、logback介绍

    Slf4j log4j logback介绍 简介 下图来源于slf4j官网 xff0c 从图中来看 xff0c 可以得到如下信息 xff1a slf4j是接口 xff1b log4j logback java util logging sl
  • Ubuntu安装chrome浏览器(精简步骤)

    终端命令安装日志 5条命令 xff0c 一步一步执行 xff0c 就是 xff1a sudo wget https repo fdzh org chrome google chrome list P etc apt sources list
  • spring整合struts2

    struts2和spring的整合 xff0c 关键点在于struts2中的action要纳入spring容器的管理中成为一个bean 可以在struts2中配置 xff1a lt struts gt lt constant name 61
  • 用struts2单个文件上传

    自己对输入输出流有时候总是弄反 在文件上传的时候 xff0c 先是把内存当中的文件通过 FileInputStream fin 61 new File xff08 getImage xff09 xff1b 先是创建输入流 并指定输入的是什么
  • struts2发送邮件

    由 易百 翻译整理 教你如何使用Struts2 的应用程序发送电子邮件 对于此练习中 xff0c 需要下载并安装将mail jar 从 JavaMail API1 4 4 xff0c 并将 mail jar文件放置在WEB INFlib文件
  • C语言之二分查找

    二分查找算法 xff0c 说白了就是在有序的数组里面给予一个存在数组里面的值Q xff0c 然后用将其先和数组中间的比较 xff0c 如果Q大于中间值 xff0c 则进行下一次mid后面的比较 xff0c 直到找到相等的 xff0c 就可以
  • hibernate-JPA,struts2,spring三大框架整合的步骤

    S2SH的整合 Hibernate JPA 43 Struts2 43 Spring 1 什么是S2SH的整合 Struts2 43 Spring 43 Hibernate 各个框架在S2SH中的作用 Spring 负责管理Struts2和
  • 广播电视相关信息系统安全 等级保护测评要求

    http www ahgd gov cn data upfile 1 files 1211 1 12111210240962 pdf
  • JAVA之希尔排序

    public class xier public static void main String args int A 61 new int 10 9 8 7 6 5 4 3 2 1 A 61 xier shellSort A 10 for

随机推荐

  • JAVA语言之快速排序

    package com paixu public class kuaipai 64 param args public static void main String args int a 61 new int 5 4 3 2 1 0 ku
  • 计算字符个数之机试

    题目描述 写出一个程序 xff0c 接受一个有字母和数字以及空格组成的字符串 xff0c 和一个字符 xff0c 然后输出输入字符串中含有该字符的个数 不区分大小写 输入描述 输入一个有字母和数字以及空格组成的字符串 xff0c 和一个字符
  • 字符串最后一个单词的长度之机试

    题目描述 计算字符串最后一个单词的长度 xff0c 单词以空格隔开 输入描述 一行字符串 输出描述 整数N xff0c 最后一个单词的长度 输入例子 hello world 输出例子 5 用String split String str 里
  • 明明的随机数之机试

    输入描述 输入多行 xff0c 先输入随机整数的个数 xff0c 在输入相应个数的整数 输出描述 返回多行 xff0c 处理后的结果 输入例子 11 10 20 40 32 67 40 20 89 300 400 15 输出例子 10 15
  • 字符串分隔之机试

    输入描述 连续输入字符串 输入2次 每个字符串长度小于100 输出描述 输出到长度为8的新字符串数组 输入例子 abc 123456789 输出例子 abc00000 12345678 90000000 思路 xff1a 重点在于字符串的长
  • 质数因子之机试

    功能 输入一个正整数 xff0c 按照从小到大的顺序输出它的所有质数的因子 xff08 如180的质数因子为2 2 3 3 5 xff09 详细描述 xff1a 函数接口说明 xff1a public String getResult lo
  • 取近似值之机试

    题目描述 写出一个程序 xff0c 接受一个浮点数值 xff0c 输出该数值的近似整数值 如果小数点后数值大于等于5 向上取整 xff1b 小于5 xff0c 则向下取整 输入描述 输入一个浮点数值 输出描述 输出该数值的近似整数值 输入例
  • 合并表记录之机试

    输入描述 先输入键值对的个数 然后输入成对的index和value值 xff0c 以空格隔开 输出描述 输出合并后的键值对 xff08 多行 xff09 输入例子 4 0 1 0 2 1 2 3 4 输出例子 0 3 1 2 3 4 思想
  • 提取不重复的整数之机试

    输入一个int型整数 xff0c 按照从右向左的阅读顺序 xff0c 返回一个不含重复数字的新的整数 输入描述 输入一个int型整数 输出描述 按照从右向左的阅读顺序 xff0c 返回一个不含重复数字的新的整数 输入例子 9876673 输
  • 链游Farmers World【农民世界】爆火,发布一个免费开源的辅助挂机脚本

    初衷 GameFi爆火 xff0c 农民世界 崛起 xff0c 浅谈链游辅助脚本开发思路 https blog csdn net CharlesSimonyi article details 121413962 上一篇文章中 xff0c 我
  • 确定两串乱序同构之程序员面试经典

    给定两个字符串 xff0c 请编写程序 xff0c 确定其中一个字符串的字符重新排列后 xff0c 能否变成另一个字符串 这里规定大小写为不同字符 xff0c 且考虑字符串重点空格 给定一个string stringA 和一个string
  • 基本字符串压缩之程序员面试经典

    利用字符重复出现的次数 xff0c 编写一个方法 xff0c 实现基本的字符串压缩功能 比如 xff0c 字符串 aabcccccaaa 经压缩会变成 a2b1c5a3 若压缩后的字符串没有变短 xff0c 则返回原先的字符串 给定一个st
  • 像素翻转之程序员面试经典

    有一副由NxN矩阵表示的图像 xff0c 这里每个像素用一个int表示 xff0c 请编写一个算法 xff0c 在不占用额外内存空间的情况下 即不使用缓存矩阵 xff0c 将图像顺时针旋转90度 给定一个NxN的矩阵 xff0c 和矩阵的阶
  • 清除行列之程序员面试经典

    请编写一个算法 xff0c 若MxN矩阵中某个元素为0 xff0c 则将其所在的行与列清零 给定一个MxN的int 矩阵 C 43 43 中为vector lt vector gt mat 和矩阵的阶数n xff0c 请返回完成操作后的in
  • JAVA语言之归并排序

    package com paixu public class guibing public static void main String args int A 61 new int 5 3 4 2 1 A 61 guibing merge
  • 程序员面试经典之链表分割

    题目描述 编写代码 xff0c 以给定值x为基准将链表分割成两部分 xff0c 所有小于x的结点排在大于或等于x的结点之前 给定一个链表的头指针 ListNode pHead xff0c 请返回重新排列后的链表的头指针 注意 xff1a 分
  • JAVA语言之计数排序

    非比较的计数排序可以用桶排序的方式实现 代码如下 xff1a package com paixu public class jishu public static void main String args int A 61 new int
  • JAVA语言之基数排序

    基数排序简而言之可以创建0 9余数共十个桶 代码如下 xff1a public class jishu 1 public static void main String args int A 61 new int 54 35 48 36 2
  • 链式A+B之程序员面试经典

    有两个用链表表示的整数 xff0c 每个结点包含一个数位 这些数位是反向存放的 xff0c 也就是个位排在链表的首部 编写函数对这两个整数求和 xff0c 并用链表形式返回结果 给定两个链表ListNode A xff0c ListNode
  • Android逆向【4】:暴力破解APK签名校验,愉快的重新打包微信支付宝APK

    回顾 Android逆向小技巧 xff1a 批量注入日志 xff0c 打印目标程序执行流程 在上一篇2019年的文章中 xff0c 我们使用python写了一个简单的文本处理工具 xff1a https github com encoder