背景
某天我和往常一样把需要测试的uniapp代码打包成apk、aab、ipa文件,然后把apk、aab文件的压缩包上传到google云盘、ipa上传到Testfilght,方便测试人员进行测试。
然而测试人员告诉我,你的apk压缩包有病毒提示(google硬盘在下载时会进行病毒分析),请解决完,再让我测试。
我一想,什么病毒?
这里有个小点
- google硬盘上传apk文件后,再去下载也会报未知风险,所以压缩一下就解决了
- 其次文件夹的名字不能大写
技术栈
- uniapp + vue3 + vite + unocss + ts + uview-plus
查看问题
我心想怎么会这样,于是本着查看与复现问题的心,我也尝试下载,结果发现,apk压缩包确实有病毒提示,但aab文件没有病毒,这就匪夷所思了呀
因为apk、aab文件的代码与打包的协议的都是一模一样,就是打包后的渠道包不一样,怎么会导致打包出来,一个有病毒,一个没病毒,这就很奇怪
前期的猜测与尝试
- 使用病毒分析工具,看看有没有什么异常的,VirusTotal
- 版本回退,使用上一次打包的版本的代码,然后对比分析。因为上一次打包出来的apk可没有报错
- uniapp官方可能有些病毒,需要去社区里面进行查看
- 某些依赖有病毒
实践与验证
- 使用病毒分析工具,只分析出了一个可能的误报的病毒:
Acronis (Static ML);这不太好排查,主要核心的package.json、vite.config.js、mainfest.json,这些都没有变化;唯一变化的不过是某些页面的代码 - 版本回退,发现使用了之前的版本打包出来的apk也有病毒,这就奇怪了,为什么?
- uniapp官方申明过,他们没有任何病毒,参考
- 考虑到我的package.json没有变化,所以依赖病毒可以略过
绕过与解决病毒的尝试
看到上图中的一个很关键的词语——投诉,于是我就想把自己的问题反馈给google云盘,希望能有点结果(实际上真没啥结果,都不回复你)
经过以上俩个测试,我并没有发现很关键的点,直接尬住了
此时的想法是绕过病毒检查,先让测试人员测apk,毕竟aab文件是用来上传到google play的,而且不好在手机上测试。
那怎么办呢,如果测试要正常继续下去,可以先让apk绕过病毒检查,毕竟aab没有病毒,我的做法是加密apk的压缩包,这样就能绕过病毒检查了
僵局
但是吧,测试人员还是不依不饶说,不能测试,等到病毒问题解决了在测试。此时就陷入了一个漫长的僵局,我无法解决这个问题,只能先暂时搁置,但仍然被催,即使说,这是google的误报也不行
转机
有时候需要大胆尝试
我突然想到,aab文件可以转apk的,如果aab文件没病毒,那理论上转换出来的apk也是没有病毒的,而且不是很复杂,我之前有研究过,具体流程如下:
- 下载,
bundletool jar,这是一个google官方给的工具,下载地址 - 转换,在有
bundletool jar的文件夹下执行转换命令 - 解压,因为转换后有个
.apks的产物,这个产物其实压缩包,需要用命令进行解压
然后我就开始了我的大胆尝试
转换命令
# 如果你是mac可能要加,window不清楚,禁用 mac 的 Zsh 的 history expansion(临时)
# 因为如果你的证书的密码有!,命令会被截断
set +H
# 转换命令模版
java -jar bundletool.jar build-apks
--bundle=aab文件路径 # /xxx/xxx/xxx.aab
--output=转换产物目标路径 # /xxx/xxx/xxx.apks
--mode=universal
--ks=证书路径
--ks-pass='pass:证书密码' # 前缀pass: ,如果有!,需要引号
--key-pass='pass:证书密码' # 前缀pass: ,如果有!,需要引号
--ks-key-alias=证书别名
# 转换命令需要一行
java -jar bundletool.jar build-apks --bundle=/xxx/xxx.aab --output=/xxx/xxx.apks --mode=universal --ks=/xxx/xxx.keystore --ks-pass='pass:证书密码' --key-pass='pass:证书密码' --ks-key-alias=证书别名
转换命令解释
| 参数 | 意义 | 来源 | 是否必须 |
|---|---|---|---|
-jar bundletool.jar | 执行 bundletool JAR 文件 | 你下载的 bundletool-all.jar 文件 | ✅ |
build-apks | 命令类型,表示构建 .apks 文件 | 固定写法 | ✅ |
--bundle=app-release.aab | 要转换的 App Bundle 文件(AAB)路径 | Gradle 构建或手动打包生成的 .aab | ✅ |
--output=app.apks | 输出 .apks 文件的路径 | 你定义的任意文件名,后缀 .apks | ✅ |
--ks=your-release-key.jks | 指定签名的 keystore 文件路径 | 你生成的签名证书(用 keytool 创建) | ✅(发布用) |
--ks-key-alias=your-key-alias | keystore 中的别名(alias) | 创建 keystore 时设置的名称 | ✅(发布用) |
--ks-pass=pass:your-keystore-password | keystore 文件的密码 | 你设置的密码(推荐用 env 变量代替) | ✅(发布用) |
--key-pass=pass:your-key-password | 密钥条目的密码 | 和 alias 相关联的密码 | ✅(发布用) |
解压命令
unzip 目标路径 -d 解压路径
解压完就能得到2个文件,其中一个是unviersal.apk,这个就是转换出来的apk,另外一个是toc.pb
注意点
- 上述命令我是在mac上运行的,window没试过,但思路是一样的
- 证书密码有!字符,在mac端会被截断,需要set +H,并且用引号包围
- 前缀的pass:,不能忘记加
- 需要在bundletool jar的父级文件夹运行转换命令,简单来说那个目录有这个,就在那个目录下运行转换命令
结果
在经过我的转换后,我运行了下新的apk,发现能够运行,并且也没有任何病毒提示,我大喜过望,赶紧让测试人员测试,此事就暂时告一段落了,反正得让测试进行测试
尾声
apk的病毒还是没有解决,但新的apk没有病毒,我正在对比2者的差异化,希望能找出一些蛛丝马迹
后续
后续就是只能先认为这是个误报,后续文章