hkt1998

hkt1998

安卓APP渗透基础 —— APK安装包的签名机制

2024-07-12

签名过程类似于对文件办法数字证书。签名后的APK文件在安装时,Android系统会对其进行验证,以确保文件未被篡改且来自“可信的开发者”。“可信的开发者”我打上了双引号,因为默认的情况下安卓没有办法判断开发者是否可信。

签名机制

APK签名的原理基于公钥加密和数字证书的机制。具体来说,签名过程包括以下几个步骤:

  1. 生成密钥对:开发者使用密钥生成工具(如keytool)生成一对公钥和私钥。公钥用于验证签名,私钥用于生成签名。

  2. 计算摘要:开发者使用哈希算法(如SHA-256)对APK文件的内容进行计算,得到一个固定长度的摘要。这个摘要是APK文件内容的唯一表示。

  3. 生成签名:开发者使用私钥对摘要进行加密,生成签名文件。签名文件通常包含签名数据、公钥以及开发者证书等信息。

  4. 添加签名文件:开发者将签名文件添加到APK包中,通常放在META-INF目录下。

上面的签名过程只是一个非常非常简单的描述,具体不同签名版本实现的机制有些不同。

签名范围

签名过程中是否对所有文件都进行了签名计算,是不是APK改动了任意一个字节签名就会不通过?

在签名过程中,并非对所有文件都直接进行了签名计算,而是采用了特定的签名机制来确保APK的完整性和来源的可靠性。具体来说,Android APK的签名过程大致如下:

  1. 计算Hash值:首先,对未签名的APK里面的所有文件(除了META-INF目录,这个目录通常用于存放签名信息)计算hash值。这一步骤是为了生成每个文件的唯一摘要,以便后续进行验证。

  2. 保存Hash值:计算得到的hash值会被保存在一个名为MANIFEST.MF的文件中。这个文件记录了APK中每个文件的hash值,但不包括META-INF目录本身。

  3. 再次计算Hash值并签名:接着,对MANIFEST.MF文件本身也计算hash值,并将这些hash值以及MANIFEST.MF文件本身的信息保存在CERT.SF文件中。然后,使用开发者的私钥对CERT.SF文件(或其中的hash值)进行签名,并将签名结果保存在CERT.RSA文件中。

关于APK改动后签名验证的问题:

  • 改动任意一个字节:如果APK中的任何一个文件(除了META-INF目录下的文件)被改动,那么该文件的hash值将会发生变化。在安装或升级过程中,系统会重新计算APK中所有文件的hash值,并与MANIFEST.MF中记录的hash值进行比较。如果发现有任何不匹配的情况,签名验证将会失败,导致APK无法安装或升级。

  • META-INF目录的改动:虽然META-INF目录下的文件本身通常不包含APK业务逻辑的代码或资源,但直接修改这个目录也可能会影响签名的验证。因为系统可能会检查META-INF目录下文件的完整性和签名信息的一致性。然而,在某些情况下,如添加空目录或特定类型的文件到META-INF目录下,可能不会影响原有的签名验证(但这并不是一种推荐的做法,因为它可能引入未知的风险)。

不同签名版本之间的比较

签名版本

V1 (JAR签名)

V2 (APK签名方案v2+)

V3 (APK签名方案v3+)

V3.1 (APK签名方案v3.1+)

V4 (APK签名方案v4+)

引入的Android版本

早期版本

7.0 (API 24)

9.0 (API 28)

13

11.0

签名机制

整体签名

增量签名

增量签名

增量签名

基于Merkle哈希树

哈希算法

MD5, SHA1

SHA256

SHA256

SHA256

Merkle哈希树

签名算法

RSA, DSA

ECDSA

RSA, ECDSA

RSA, ECDSA

-

增量签名

-

安全性增强

基础

高效验证、更广覆盖范围

更强大签名算法、密钥轮替支持

解决V3轮替问题,支持SDK版本定位

支持ADB增量APK安装

兼容性

所有Android版本

与V1兼容

与V1、V2兼容

与旧版Android兼容

需要v2或v3签名作为补充

主要用途

早期应用的签名

提高验证性能和完整性保证

提供更高的安全性,支持密钥轮替

改进V3签名方案,增强密钥轮替支持

开发调试场景,支持ADB增量安装

应用市场签名机制对比

由于安卓在安装APP时仅将APK中的签名与证书校验,意思就是仅能保证这个APK是由这张证书的所有者提供且没有被篡改的。但用户又如何判断这张证书就是正规来源的证书呢?其实没有办法,证书上只提供了所有者的一些基本信息,比如名称,这个名称是在创建证书时随意起的,所以没有任何说服力。

而苹果应用市场那边就不同了:

iOS应用商店

  • 开发者在苹果开发者中心创建证书和描述文件。

  • 证书用于证明开发者身份,并与私钥配对用于签名应用程序。

  • 描述文件用于授权安装应用程序,包含应用程序ID、设备UDID列表和证书信息。

安卓应用商店

  • 开发者自行生成签名证书(如使用keytool工具),并将其用于对APK文件进行签名。

  • 签名证书由开发者保管,并在需要时用于签名新的APK版本。

可以看到一个明显的区别就是苹果的证书是官方统一管理的,至少在一定程度上能控制开发者的合法性,比如上传认证资料等。而安卓这边,开发者自行生成证书,虽然通过签名技术保证了完整性,但真实性没有保护,最后完整性也得不到保障。

所以现在各手机品牌陆续推出自己的应用市场,效仿苹果的那种模式,APK采用统一办法的证书签名才能上应用市场,比如华为应用市场、小米应用市场等。