首页 > 编程知识 正文

android系统签名工具,android插件化原理

时间:2023-05-04 19:09:16 阅读:41564 作者:3660

8种机械键盘轴体的比较

本人,买写代码的键盘,红轴和茶轴怎么选?

背景

由于业务需求,我们需要统计用户下载和安装apk的来源,因此对于不同的APP应用市场和活动页面,我们发布的apk有相应的渠道信息。 对于apk有相应的渠道信息,网上已经有很多成熟的方案。 例如,可以使用gradle构建不同的通道包。 但是,考虑到打包效率的问题,我们没有使用gradle构建多渠道的方式,而是使用美团的自动生成渠道打包方式来实现的。

由于此方法不适合APK Signature Scheme v2机制,因此在我们的项目中使用v2的签名机制一直处于关闭状态。 而且由于最近的安全问题,我们必须在项目中使用v2机制开始签名apk。 美团为v2签名机制提供了另一种生成通道数据包方案,但在使用之前,我想了解更多的安卓签名机制。

关于APP签名

“APP”标志在安卓系统中起着极其重要的作用,主要表现在: 检查apk是否被伪造或篡改

升级APP时,检查目标apk是否与原始APP匹配

代码或数据共享。 一个APP应用程序可以向使用同一证书签名的另一个APP应用程序发布自己的功能或数据

APK格式

apk文件本质上是zip格式的文件:

apk签名基于该文件格式,追加apk文件一部分数据的数字签名信息; 在验证时,读取该部分签名信息,验证与其对应的部分数据。

Zip文件格式

apk的本质是zip格式的文件,因此在理解apk签名之前,必须了解zip文件格式。

. ZIP文件格式概述: 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15[文件头1]

[文件数据1]

数据描述符记录1

水平。

水平。

水平。

[文件头n]

[文件数据n]

数据描述符记录n

[归档解密标头]

存档附加数据记录

中央目录结构

中央目录记录的Zip64结尾

中央目录定位器的Zip64结尾

中央目录记录的结尾

其中有一些数据在后续漏洞和签名分析中起重要作用,下面将详细介绍:

本地文件头:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16----a文件头------------

标头签名4字节[开始于0](0x04034b50 ) ) ) ) ) ) ) ) ) ) ) ) )。

所需的2字节版本[开始4]

一般用位标志2字节[开始6]

压缩方法2字节[开始8](8=deflate; 0=未完成)

文件的上次修改时间为2字节[开始10]

文件的上次修改日期为2字节[开始12]

crc-32 4字节[开始14]

压缩后的大小4字节[开始18]

解压缩后的大小4字节[开始22]

文件名的长度为2字节[开始26]

附加字段长度2字节[开始28]

文件名

附加字段变量

中心目录1结束

2

3

4

5

6

7

8

9

10

11----I中央目录记录的结束--------

中心目录签名4字节[开始0](0x06054b50 )注:使用“冒泡”从文件末尾跟踪以找到此签名。

磁盘编号2字节[开始4]

中央目录开始磁盘编号2字节[开始6]

此磁盘上的中央目录中的条目总数为2字节[开始8]

中心目录中的条目总数2字节[开始10]注意:文件总数,文件夹也算作一个文件。

中央目录的大小4字节[开始12]

中央目录相对于第一张磁盘的偏移4字节[开始16]

. ZIP文件注释长度2字节[开始20]

.ZIP 文件注释 变量 [开始 22]

而解析zip文件的过程,则是通过从文件尾部逆向查找End of Central Directory的起始标识,从而解析对应的Central Directory,进而解析zip里面的所有文件信息。

APK Signature Scheme v1

​v1 scheme是基于jar签名来实现,而jar的签名机制,则是往zip文件中,插入一个META-INFO文件夹,然后将所有与签名相关的信息都保存在这个文件夹下。同样,通过对比已签名和未签名apk解压后的META-INFO文件夹下的文件,以分析v1 scheme签名的实现原理:

相比未签名的apk,已签名的apk的META-INFO文件夹下,多了{name}.RSA和{name}.SF文件,根据JAR文件格式描述可知:MANIFEST.MF 保存了apk中所有需要校验的文件所对应的摘要

{name}.SF 保存了MANIFEST.MF中所对应每块数据所对应的摘要

{name}.RSA 保存了对应非对称加密算法所使用的公钥和{name}.SF文件经过非对称加密后的密文

以上三个文件的生成逻辑,都可以在build/tools/signapk/src/com/android/signapk/SignApk.java源码文件中找到。MANIFEST.MF文件的生成,在的addDigestsToManifest方法中。签名工具会遍历apk文件中的所有文件(过滤其中的一些文件),并针对这些文件通过摘要算法生成摘要信息并base64编码之后保存在MANIFEST.MF文件中:

{name}.SF文件的生成,则在writeSignatureFile方法中。签名工具会读取MANIFEST.MF文件中的所有section,然后针对每个section通过摘要算法生成摘要信息并base64编码之后保存在{name}.SF文件中,此处很容易让人误解{name}.SF文件中的内容是经过非对称加密之后所产生的,然而并非如此,该方法连加密所需要用到的公钥和私钥都没有被传入,只是针对每个section进行摘要并base64编码而已:

{name}.RSA文件的生成,在writeSignatureBlock方法中。该方法将生成的{name}.SF文件经过非对称加密生成密文之后,与公钥合并生成{name}.RSA文件:

而在对apk进行验签的过程,则是与生成apk相反的过程,系统会先根据{name}.RSA中的公钥和密文,还原出原文并与{name}.SF对比,以验证{name}.SF文件是否被修改过,然后在根据MANIFEST.MF文件(读取MANIFEST.MF的时候,会根据MANIFEST.MF中section信息进行验证apk中的文件是否会修改过的)中的section与{name}.SF文件中的section进行对比验证。

由于v1签名不会对META-INFO文件夹内的文件进行校验,所以可以通过在META-INFO文件夹下添加文件以达到APK携带渠道等信息的目的。

APK Signature Scheme v2

鉴于APK Sinature Scheme v1存在安全漏洞,所以google推出了新的签名校验的方式:APK Signature Scheme v2。

v2是针对整个文件进行签名校验的机制,所以具有更高的安全性和更好的校验速度。其实现机制在于,在ZIP 的Central Directory 部分前面插入一个APK Signature Block,如下图:

APK Signature Scheme v2 Signing Block

Signing Block 格式如下:1

2

3

4

5

6

7

8[size of block] 8 字节

[length prefixed ID-values pairs] 8 字节 + 4 字节 + (length - 4)字节 (8字节的长度,标识后面这对id和value的长度)

.

.

.

[length prefixed ID-values pairs]

[size of block] 8 字节

[magic] 16 字节,内容为"APK Sig Block 42"

而apk的签名校验信息(公钥及加密的密文)则是存在ID为0x7109871a的value中,所以获取apk签名校验信息的过程,其实就是查找Signing Block中id为0x7109871a的过程:

而在查找签名校验信息的过程中,系统会过滤ID为其他值的键值对。

APK Signature Scheme v2签名方式

v2签名会计算除Signing Block之外的所有数据的摘要,然后使用非对称加密之后保存在Signing block中:

在对apk进行签名的时候,签名工具会将原的Central Directory前的数据(不包含signing block)、Central Directory和End of Central Directory分别进行分段并计算摘要(每段都分成1M大小的数据,然后计算0xa5 + Chunk Lenght(4 byte) + Chunk的摘要),然后再针对计算出来的摘要数据(计算0xa5 + Chunks Count(4 byte) + Chunks Digests)再进行一次摘要计算,从而得到最终待加密的摘要数据,最后合并摘要加密后的数据和证书的公钥组成Signing Block。

其中有个让人困惑的地方是,签名工具在Central Directory前面插入Signing Block之后,会导致End of Central Directory中保存的Central Directory offset变更(不然会破坏其原有的ZIP格式而导致无法解压出其中的文件):

那么这必然会导致后续验签的时候,根据End of Central Directory计算出来的摘要数据与之前不匹配。很多资料或者博文都没有提到这点是怎么解决的,甚至还有资料说Central Directory offset字段不参与计算摘要的,但是通过查看计算摘要信息的算法中,并没有对该字段进行特殊处理的:

其中contents数组对应上面的beforeCentralDir, centralDir 和 eocd

既然这个问题,在生成签名的时候没有绕过,那么只可能是在验签的时候进行绕过了。事实上,在验签的过程中,系统在获取到End of Central Directory数据之后,会先将Central Directory offset字段还原回没有Signing Block的时候Central Directory的offset(即Signing Block的起始位置):

关于APK Shgnature Scheme v1的漏洞

“MasterKey”漏洞 & “Janus”漏洞 & “9950697”漏洞

APK Signature Scheme v2的不足

由于Android的签名校验机制是向前兼容的,所以Signature Scheme v2是在v1的基础上,再次进行了全文件的摘要验签,以保证即使使用v2进行签名,在Android N之前的系统中也能够正常校验签名,所以本质上使用v2签名,同时也会有v1的签名信息的。而Android N及之后的签名校验流程如下:

系统会先检测APK是否存在v2的Signing Block,如果没有,则执行v1的校验机制。由于Android N之前的系统,并不存在v2的校验机制,所以即使使用了v2的签名,在Android N之前的系统上,也不能做到防篡改的(毕竟之前的系统已经发布出去了,没法进行修改逻辑)。

鉴于以上验签流程,可能有人会想通过破坏v2签名的APK的Signing Block块,以达到让Android N及以上系统走v1校验的流程,从而使用漏洞来篡改APK。但可惜此方式是行不同的,对比v1和v2签名的APK,v2并不只是多了Signing Block块,而且对应的{name}.SF文件内容也不一样:

v2的{name}.SF文件中,标识了APK是使用Signature Scheme v2进行签名的,如果检测不到Signing Block,同样会报找不到签名信息错误的。

参考文献

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。