APK签名替换检测
apk二次打包的危害
apk二次打包是android应用安全风险中的一部分, 一般是通过反编译工具向应用中插入广告代码与相关配置,再在第三方应用市场、论坛发布。打包党对移动app带来的危害有以下几种:
- 插入自己广告或者删除原来广告;
- 恶意代码, 恶意扣费、木马等;
- 修改原来支付逻辑;
上述恶意行为严重危害移动产品和用户利益,同时也影响企业口碑。
apk的签名机制
google设计apk的签名机制就是防止两个问题:
- 不让别人修改apk包,防止反编译后二次打包;
怎么做到不让别人二次打包呢?android系统在安装apk时,会先去确认是否有签名、签名是否能对上; - android系统在安装apk包时,不允许安装同一个包名但是签名不一样的apk;
下面开始分析apk打签名的流程:
需要了解的背景知识
自行去百度,了解概念即可;
- 数据摘要(数据指纹)、md5\sha-1对称加密算法
- 非对称加密算法
- 数字签名、数字证书
- 手动签名apk包
1.查看meta-inf文件
将.apk包修改后缀成.zip,解压之后打开该文件夹,找到meta-inf目录。
签名就是围绕这三个文件开始的。
2.先看第一个文件manifest.mf
这个文件里面包括了apk文件中所有文件的数据摘要值。相当于对每个单独(除了这三个)的文件都做了数据指纹。
3.在看第二个文件cert.sf
和manifest.mf文件差不多,唯一的差别在于,多了一行sha1-digest-manifest: kderpmankkb5mxceo/t5oxrgapg=
,这行就是manifest.mf的数据摘要。
4.最后看第三个文件cert.sf
把之前的cert.sf文件用私钥计算出一个加密值,这个加密值称为签名,所以这个文件包含了签名和公钥;
如果是在windows系统下,推荐使用cmder.exe软件使用如下命令。
d:\programfiles\cmder>openssl pkcs7 -inform der -in "c:\app-debug - 副本\meta-inf\cert.rsa" -noout -print_certs -text warning: can't open config file: /usr/local/ssl/openssl.cnf certificate: data: version: 1 (0x0) serial number: 1 (0x1) signature algorithm: sha1withrsaencryption issuer: cn=android debug, o=android, c=us validity not before: dec 27 09:26:22 2018 gmt not after : dec 19 09:26:22 2048 gmt subject: cn=android debug, o=android, c=us subject public key info: public key algorithm: rsaencryption public-key: (1024 bit) modulus: 00:89:e0:b4:29:a9:62:b1:44:48:b8:35:f2:8a:06: 91:c7:36:44:1a:d2:b3:97:fd:58:b5:84:35:fc:83: 09:50:f5:85:83:d9:bc:12:a8:da:da:cf:f0:10:d0: 4d:9f:a5:9d:7f:de:b6:4e:1e:94:36:c4:f4:44:45: 4e:44:f5:97:9f:f3:62:3f:5f:9d:ce:a6:18:73:22: 62:28:79:f7:46:f8:d6:f7:ca:46:e3:3f:dd:a8:ac: b7:aa:cb:77:7c:47:16:89:d1:d5:f8:47:e5:21:28: 87:f8:a6:dd:ee:ed:01:da:b5:06:49:04:19:49:46: d8:0a:a6:bb:b4:b5:c9:56:79 exponent: 65537 (0x10001) signature algorithm: sha1withrsaencryption 79:3c:29:c5:3c:e7:d8:28:e1:5c:2a:1d:ce:31:cb:e6:a5:09: d0:10:d8:e5:74:e9:b5:80:4a:63:76:f4:67:ee:8c:f1:eb:04: 8f:23:f4:f6:c2:f7:a5:99:af:c5:be:8f:70:6d:dc:3e:b3:db: ca:b2:64:e1:0c:ca:ce:fe:16:1f:3b:00:83:b5:f8:be:8a:b4: 7e:a9:94:fe:77:1f:67:ff:4f:54:87:66:f4:97:be:ce:38:54: 51:b4:ce:a8:23:60:92:e3:bf:5d:21:11:50:c9:c2:40:b4:69: 89:fe:4f:66:84:17:42:91:af:af:bd:e9:47:24:f8:db:74:70: d0:87
证书内容概况:
用来管理私钥仓库的命令:
d:\programfiles\cmder>keytool -printcert -file "c:\app-debug - 副本\meta-inf\cert.rsa" 所有者: c=us, o=android, cn=android debug 发布者: c=us, o=android, cn=android debug 序列号: 1 有效期为 thu dec 27 17:26:22 cst 2018 至 sat dec 19 17:26:22 cst 2048 证书指纹: md5: 41:41:89:25:4c:9b:91:6d:16:91:20:6c:1d:d7:61:2f sha1: 73:fc:5a:9f:5d:7a:cc:93:14:8d:f1:13:37:e6:11:c2:86:a4:3d:34 sha256: 32:33:24:4f:1c:4e:6e:78:3f:f2:c4:59:cd:19:9f:43:bc:ac:1a:23:cb:78:72:9a:0e:61:c9:b3:5d:4c:b9:c1 签名算法名称: sha1withrsa 主体公共密钥算法: 1024 位 rsa 密钥 版本: 1
总结
apk生成后签名不能更改,因为没有私钥。但能替换签名,因为android系统在安装apk的时候只校验签名的正确性。
一个apk文件,通过使用androidkiller二次编译,我对比了原apk和编译后的apk的./meta-inf/cert.rsa文件,发现确实是被替换了。
签名的过程可以想象成发件人和收件人的处理流程,也是一个双向的动作,可以大致理解成下图流程:
可以把上图的客户1替换成打包apk的过程,把服务器替换成android手机安装apk的过程,当系统拿着cert.rsa里面的公钥和apk原文解密出的hash值和cert.sf文件里面的hash值不一致时,就不会去安装。
检测是否能替换签名
二次打包成功的前提是能替换签名,并且apk没做签名校验。而签名验证的方式有三种:
apk包没有做签名校验
直接替换签名即可,下面将介绍替换签名的步骤;- apk包做了签名校验
- java代码校验
难点在于找到校验的java代码,注释掉即可; - .so文件校验
难点在于找到校验的c代码,注释掉即可; - 加壳
难点在于得先脱壳;
- java代码校验
替换签名步骤
工具:
androidkiller_v1.3.1 (下载地址:)
步骤:
使用androidkiller_v1.3.1工具,里面有个编译功能,就能做到二次打包,原理就是替换签名值。
我一般修改版本号来证明能二次打包:
反编译后在androidmanifest.xml 里直接修改版本号,如果在androidmanifest.xml文件中无法看到 versioncode和versionname字段,则在apktool.yml文件中打开找到,对应修改versionname字段的数字大小即可。
修复方式
- so层校验签名
- 网络校验签名
- apk加固