转: APK签名校验绕过
转: http://drops.wooyun.org/mobile/4296
APK签名校验绕过
0x01 Android签名机制
将APK重命名为zip文件,然后可以看到有个META-INF的文件夹,里面有三个文件,分别名为MANIFEST.MF、CERT.SF和CERT.RSA,这些就是使用signapk.jar生成的签名文件。
1、 MANIFEST.MF文件:
程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码。具体代码见这个方法:
| 1 | privatestaticManifest addDigestsToManifest(JarFile jar) | 
关键代码是
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | for(JarEntry entry: byName.values()) {     String name = entry.getName();     if(!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&         !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&         (stripPattern == null||!stripPattern.matcher(name).matches())){         InputStream data = jar.getInputStream(entry);         while((num = data.read(buffer)) > 0) {         md.update(buffer, 0, num);       }       Attributes attr = null;       if(input != null) attr = input.getAttributes(name);       attr = attr != null? newAttributes(attr) : newAttributes();       attr.putValue("SHA1-Digest", base64.encode(md.digest()));       output.getEntries().put(name, attr);    }} | 
之后将生成的签名写入MANIFEST.MF文件。关键代码如下:
| 1 2 3 4 5 | Manifest manifest = addDigestsToManifest(inputJar);je = newJarEntry(JarFile.MANIFEST_NAME);je.setTime(timestamp);outputJar.putNextEntry(je);manifest.write(outputJar); | 
2、 生成CERT.SF文件:
对前一步生成的Manifest,使用SHA1-RSA算法,用私钥进行签名。关键代码如下:
| 1 2 3 4 5 6 7 | Signature signature = Signature.getInstance("SHA1withRSA");signature.initSign(privateKey);je = newJarEntry(CERT_SF_NAME);je.setTime(timestamp);outputJar.putNextEntry(je);writeSignatureFile(manifest,newSignatureOutputStream(outputJar, signature)); | 
3、 生成CERT.RSA文件:
生成MANIFEST.MF没有使用密钥信息,生成CERT.SF文件使用了私钥文件。那么我们可以很容易猜测到,CERT.RSA文件的生成肯定和公钥相关。 CERT.RSA文件中保存了公钥、所采用的加密算法等信息。核心代码如下:
| 1 2 3 4 | je = newJarEntry(CERT_RSA_NAME);je.setTime(timestamp);outputJar.putNextEntry(je);writeSignatureBlock(signature, publicKey, outputJar); | 
在程序中获取APK的签名时,通过signature方法进行获取,如下:
| 1 2 3 4 5 6 | packageInfo = manager.getPackageInfo(pkgname,PackageManager.GET_SIGNATURES);signatures = packageInfo.signatures;for(Signature signature : signatures) {    builder.append(signature.toCharsString());}signature = builder.toString(); | 
所以一般的程序就是在代码中通过判断signature的值,来判断APK是否被重新打包过。
0x02 签名绕过方式
在讲签名绕过的方式前,需要先明确DEX校验和签名校验:
1.将apk以压缩包的形式打开删除原签名后,再签名,安装能够正常打开,但是用IDE(即apk改之理,会自动反编译dex)工具二次打包,却出现非正常情况的,如:闪退/弹出非正版提示框。可以确定是dex文件的校验
2、将apk以压缩包的形式打开删除原签名再签名,安装之后打开异常的,则基本可以断定是签名检验。如果在断网的情况下同样是会出现异常,则是本地的签名检验;如果首先出现的是提示网络没有连接,则是服务器端的签名校验.
2.1.Java层校验
获取签名信息和验证的方法都写在android的java层。实例如下:
1、使用APKIDE反编译APK,不做任何操作,然后直接回编译,安装后运行,提示如下:

2、在APKIDE中搜索signatures(或者搜索错误提示),定位到签名验证的代码处。

3、此处就是获取签名的,然后找程序判断签名的地方,进行修改,如下图,if-nez是进行判断的地方,将ne修改为eq。即if-eqz v2, :cond_0。则程序就可以绕过本地的签名交易。


2.2.NDK校验
将关键代码放到so中,在底层获取签名信息并验证。因为获取和验证的方法都封闭在更安全的so库里面,能够起到一定意义上的保护作用。实例如下:
1、使用APKIDE反编译APK,不做任何操作,然后直接回编译,安装后运行,程序直接退出,无任何提示。
2、在APKIDE中搜索signatures(或者搜索错误提示),定位到签名验证的代码处。

3、使⽤用JD-GUI打开AppActivity,可以看到,此处是获取包名,然后进⾏行MD5计算。

4.在程序中搜索getSignature,发现并没有调⽤用此函数的地⽅方,猜测在so⽂文件中,搜索loadLibrary。

5.在代码中可以查找,可以找到调⽤用的是libcocos2dcpp.so
6.使⽤用IDA打开libcocos2dcpp.so,然后搜索getSiganture,找到调⽤用此函数的地方。

从代码中可以看到,此函数调⽤用了org.cocos2dx.cpp.AppActivity.getSignature

7、查看F5代码,发现此函数是判断签名的函数,然后我们双击此函数的调⽤者,部分代码如下。

8、从上图可以看出,只需要修改BEQ loc_11F754,让其不跳转到jjni——>error,就可以绕过签名校验。 查看HEX,使⽤010editor跳到0011F73E,修改D0为D1。成功绕过签名校验。

2.3.服务器验证
在android的java层获取签名信息,上传服务器在服务端进行签名然后返回验证结果。
如下图,网络验证时,如果网络没连接,一般都会提示错误。

既然是网络验证,肯定要把验证信息发送到服务端,然后进行验证,先看个简单的实例,下次会有个难度大的。
1、手机配置好抓包,然后抓包。第一种图是正常的APK的时候的数据包,第二个图是反编译的APK的数据包,通过对比,发现cookie中的public_key不一样,那么我们替换一下,发现可以正常使用APK的功能了。


2、将正确的public_key添加到APK中。打开反编译的代码,搜索signatures,定位到签名的代码。

可以看到,代码将signatures的值传递到V4中,然后传递到Utils->mPublicKey函数中,于是我们将正确的public_key传给V4。

然后重新打包,重新安装就可以了。
0x03.总结
java层的校验很容易就可以破解掉,在so层实现校验相对来说分析会更难点,而网络验证,如果仅仅是字符串的比较,那么也很容易破解掉。
码子码的太累了。。
后面还有几篇正在写的文章,包括so分析等等。
摘抄: http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html
转: APK签名校验绕过的更多相关文章
- APK签名校验绕过
		APK签名校验绕过 Android JNI 获取应用签名 android apk 防止反编译技术第一篇-加壳技术 android apk 防止反编译技术第五篇-完整性校验 利用IDA Pro反汇编程序 ... 
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
		Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ... 
- 一次简单的绕过apk签名校验
		朋友发来一个apk,需要分析其中的一些算法,分析过程涉及到了重新打包apk,打包后的apk运行失败,估计是apk内部有检验是否被篡改的代码.检验apk是否被篡改,简单的方法是直接校验签名,如果apk签 ... 
- Apk去签名校验详解
		某些apk为了防止重打包,使用了签名校验.所以在破解的时候我们需要破解签名校验.在定位签名校验位置时常用的关键词有sign,signature,checkSign,signCheck,getPacka ... 
- 与apk签名有关的那些概念与命令
		一.概念篇 1.消息摘要-Message Digest 消息摘要:在消息数据上,执行一个单向的hash函数,生成一个固定长度的hash值,这个Hash值就是消息摘要,也成为数字指纹. 消息摘要特点: ... 
- Android中APK签名工具之jarsigner和apksigner详解
		一.工具介绍 jarsigner是JDK提供的针对jar包签名的通用工具, 位于JDK/bin/jarsigner.exe apksigner是Google官方提供的针对Android apk签名及验 ... 
- Android APK 签名比对(转)
		Android apk签名的过程 1. 生成MANIFEST.MF文件: 程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Ba ... 
- [转]通过apk签名使应用程序有系统权限
		[转]通过apk签名使应用程序有系统权限 (2013-01-08 13:40:50) 转载▼ 标签: it 分类: Android 出处:http://blog.csdn.net/doom66151/ ... 
- Android中破解应用签名校验的后续问题处理方案(闪退和重启现象以及无效问题)
		一.前言 之前已经写了一个爆破签名校验的工具kstools,很多同学也在使用,但是也反馈了不少问题,之前一篇文章也介绍了,关于爆破之后第三方登录问题修复,这篇我们在综合说明一下一些后遗症问题,关于ks ... 
随机推荐
- AC日记——[SDOI2017]相关分析 洛谷 P3707
			[SDOI2017]相关分析 思路: 裸线段树: (玄学ac): 代码: #include <bits/stdc++.h> using namespace std; #define max ... 
- python 网络爬虫框架scrapy使用说明
			1 创建项目scrapy startproject tutorial 2 定义Itemimport scrapyclass DmozItem(scrapy.Item): title = scra ... 
- Intellij IDEA 去掉Mapper文件中的背景
			1.在setting中输入:inspection --> SQL 2.去掉背景颜色,Apply即可 
- textbox获取当前光标位置,在光标后面插入字符串
			左侧输入要复制的字符串,点击复制btn,将左侧字符串复制到后侧, 示例: 输入框 复制后 12345 12345 (光标落在3后) aaa 123aaa45(光标落在4后 ... 
- Spring MVC源码——Root WebApplicationContext
			目录 Spring MVC源码--Root WebApplicationContext 上下文层次结构 Root WebApplicationContext 初始化和销毁 ContextLoaderL ... 
- maven "Generating project in Batch mode"问题的解决
			在maven的五分钟入门里面,有这样一个命令: mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -Darc ... 
- 洛谷——P1068 分数线划定
			P1068 分数线划定 题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行.为了选拔最合适的人才,A 市对 所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试.面试分数线根 据 ... 
- 发现一个FreeSWITCH bug
			在研究FreeSWITCH视频会议的混屏问题时候发现一个bug. 已提交jira. 附上代码,问题很明显,不解释 =========================================== ... 
- 【NTT】hdu1402 A * B Problem Plus
			r·2^k+1 r k g 3 1 1 2 5 1 2 2 17 1 4 3 97 3 5 5 193 3 6 5 257 1 8 3 7681 15 9 17 12289 3 12 11 40961 ... 
- 关于abstract class 和 interface
			1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系.但是,一个类却可以实现多个interface. 2.在abstract class 中可以有自己 ... 
