Google Play Protect拦截应用之系统签名

什么是 Google Play Protect ?

Google 于2017年推出的Android端有害软件查杀功能组件,类似于Windows端的Windows安全中心。主要用于查杀sideload(也就是我们通常说的apk包)的应用,GPP(Google Play Protect)认为Google Play的审核是靠谱的,所以不会怎么去动在架GP包。

不知道各位小伙伴有没有在开启谷歌服务的设备安装Apk时,遇到过下面这种Harmful app blocked的提示?

领导一开始让我解决这个问题,我测试了无数次,在不同的手机有的设备会出现,有的设备不会出现,我是丈二和尚摸不着头脑,一脸懵逼!经过一段时间的测试,这个问题就被搁置了。

直到后来在网上看到有文章介绍 Android系统组件的签名可以规避Google Play Protect拦截应用 的方案,于是就开始了尝试。

一、制作系统签名

签名文件

签名文件需要用到的文件有两个platform.pk8platform.x509.pem,由于我们的应用不属于定制主板开发,因此使用Android源码的这两个文件就行。 这里我直接通过ChatGPT找到了AOSP镜像在GitHub上的仓库,进去搜索就得到了我需要的文件,然后下载这两个文件到本地待使用。

快捷访问aosp-mirror

签名工具keytool-importkeypair

签名工具也可以直接从GitHub上面下载,快捷访问keytool-importkeypair

注意事项:下载的文件名称应该同网上的文件名称一致,我本地下载下来后,发现后缀会自动加一个txt,如果你也有的话,需要手动去掉。

签名方法

第一步

现在你已经有签名文件platform.pk8platform.x509.pem,签名工具文件keytool-importkeypair,先将他们放在同一个文件夹。为了方便管理,最好是单独在项目根目录下创建文件夹keystores

第二步

在文件夹keystores下创建signature.sh脚本文件,脚本文件内容如下:

sh 复制代码
sh keytool-importkeypair -k ./xxx.jks -p myjks -pk8 platform.pk8 -cert platform.x509.pem -alias signApk

指令详解:

  • -k ./xxx.jks------./xxx.jks指输出的签名文件地址
  • -p myjks------myjks签名文件密码
  • -alias signApk------signApk签名文件别名
  • 这里的签名文件密码属于storePassword,默认情况下storePassword和别名的keyPassword属于同一个

第三步

AndroidStudio中可以打开脚本文件,点击左上角的绿色三角符号运行脚本

当然,也可以通过其它方式来运行脚本文件。如果是在windows下的话,双击脚本文件便可以得到运行;如果是在Linux环境下,可直接执行。有疑问可以问问大模型。

脚本执行成功后就可以得到系统签名了。

storePasswordkeyPassword补充事宜

如果你需要分别设置密钥库密码和密钥条目的密码,可以使用以下步骤:

1.创建密钥库(带密钥库密码):
sh 复制代码
keytool -genkeypair -alias tempAlias -keyalg RSA -keysize 2048 -keystore my-release-key.jks -storepass storePassword -validity 10000

这里会提示你输入密钥条目的密码(keyPassword),可以与密钥库密码(storePassword)不同。

2.导入私钥和证书

使用 keytool-importkeypair 时,如果工具支持单独的密钥条目密码,你可以设置两个密码。假设你的 keytool-importkeypair 脚本不支持单独指定密钥条目密码,你可以手动创建密钥库,然后导入私钥和证书:

sh 复制代码
openssl pkcs8 -topk8 -inform PEM -outform DER -in platform.pk8 -out platform.der -nocrypt
    keytool -importkeystore -deststorepass storePassword -destkeypass keyPassword -destkeystore my-release-key.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass keyPassword -alias signApk

这将需要你先将私钥和证书转换为PKCS12格式,然后再导入到JKS中。

实际操作示例

1. 创建带有密钥库密码的密钥库
sh 复制代码
keytool -genkeypair -alias tempAlias -keyalg RSA -keysize 2048 -keystore my-release-key.jks -storepass myjks -keypass mykeypass -validity 10000
2. 删除临时密钥条目(如果你只想保留导入的密钥):
sh 复制代码
keytool -delete -alias tempAlias -keystore my-release-key.jks -storepass myjks
3. 使用转换和导入
sh 复制代码
openssl pkcs8 -topk8 -inform PEM -outform DER -in platform.pk8 -out platform.der -nocrypt
    openssl pkcs12 -export -in platform.x509.pem -inkey platform.der -out platform.p12 -name signApk -passout pass:mykeypass
    keytool -importkeystore -deststorepass myjks -destkeypass mykeypass -destkeystore my-release-key.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass mykeypass -alias signApk

通过这些步骤,你可以分别设置密钥库密码(storePassword)和密钥条目密码(keyPassword)。在上面的例子中,myjks 是密钥库密码,而 mykeypass 是密钥条目的密码。

系统签名的使用和解惑

使用签名

上面制作好了系统签名后,就可以替换项目里面的签名文件了。

groovy 复制代码
signingConfigs{
	...

	debug{
		storeFile file("../sign/system.jks")
		storePassword "harmful"
		keyAlias "harmful"
		keyPassword "harmful"

		v1SigningEnabled true
		v2SigningEnabled true
	}
}

buildTypes {
	debug {
		signingConfig signingConfigs.debug
		proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
	}
	...
}

运行之后确实没有上面Harmful app blocked的弹窗提示了

分析签名

那么系统签名究竟做了什么呢?

查看系统签名文件

sh 复制代码
keytool -list -v -keystore AndroidOSSign.jks -alias androidOSSign
  • AndroidOSSign.jks签名文件
  • androidOSSign别名

使用上面的命令后,会要求输入密码,输入密码后就可以看到下面的信息了

ruby 复制代码
别名: androidOSSign
创建日期: 2024年6月7日
条目类型: PrivateKeyEntry
证书链长度: 1
证书[1]:
所有者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
发布者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
序列号: b3998086d056cffa
生效时间: Wed Apr 16 06:40:50 CST 2008, 失效时间: Sun Sep 02 06:40:50 CST 2035
证书指纹:
         SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
         SHA256: C8:A2:E9:BC:CF:59:7C:2F:B6:DC:66:BE:E2:93:FC:13:F2:FC:47:EC:77:BC:6B:2B:0D:52:C1:1F:51:19:2A:B8
签名算法名称: MD5withRSA(禁用)
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3

扩展:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 4F E4 A0 B3 DD 9C BA 29   F7 1D 72 87 C4 E7 C3 8F  O......)..r.....
0010: 20 86 C2 99                                         ...
]
[EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US]
SerialNumber: [    b3998086 d056cffa]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen: no limit
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 4F E4 A0 B3 DD 9C BA 29   F7 1D 72 87 C4 E7 C3 8F  O......)..r.....
0010: 20 86 C2 99                                         ...
]
]


Warning:
证书 使用的 MD5withRSA 签名算法被视为存在安全风险而且被禁用。

我们重点关注一下所有者和发布者的信息:

ini 复制代码
所有者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
发布者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US

所有者 (Owner) 和发布者 (Issuer) 字段包含以下信息:

  • CN (Common Name):通常是个人的姓名或服务器名称。
  • OU (Organizational Unit):组织单位。
  • O (Organization):组织名称(公司)。
  • L (Locality):城市或地方。
  • ST (State):州或省。
  • C (Country):国家。
  • 在自签名证书中,所有者和发布者是同一个实体。这意味着证书是由它所代表的实体自己签署的。自签名证书的所有者和发布者字段内容是相同的。

手动创建系统签名

看来系统签名主要是对所有者和发布者的信息进行了处理,那么我们可以自己进行设置吗?

当然,我们也可以根据上面的信息手动创建一个自签名,也可以得到和系统签名一个效果。

综上,我们基本上就可以解决签名的问题了。

但是,还有最后一个问题:

这个时候发现好像系统签名也不是每次都有用了。不管是通过AndroidStudio Run还是通过assemble进行打包后安装,都会时不时的出现Send app for a securitycheck的提示。虽然比起Harmful app blocked弹窗危害性没有那么大,但是也还是挺膈应人的。

我后来发现每次通过Build/Generate Signed Bundle or APK打包后安装,则没有这个弹窗了。由于测试的设备仅有一个设备,这个瓜就不保真了!

相关推荐
找藉口是失败者的习惯1 小时前
Jetpack Compose 如何布局解析
android·xml·ui
Estar.Lee6 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
温辉_xh6 小时前
uiautomator案例
android
工业甲酰苯胺8 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
少说多做3438 小时前
Android 不同情况下使用 runOnUiThread
android·java
Estar.Lee9 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯10 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey11 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!13 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟13 小时前
Android音频采集
android·音视频