浅谈extractNativeLibs


前言

  很早之前逛看雪论坛看到有人提到过一件事:安卓高版本在安装apk时可以不解压lib中的so文件,而将其直接映射到内存中实现加载。当时虽然觉得有必要了解一下这个事情,但是自己并没有碰到这种case所以就搁置了。这不最近连着两次踩到这个坑了,就正好拿出来水一篇文章,这次的关键字是extractNativeLibs

extractNativeLibs介绍

什么是extractNativeLibs

  extractNativeLibs是AndroidManifest.xml中的一个字段,它的官方描述如下

此属性指示软件包安装程序是否将原生库从 APK 提取到文件系统。如果设置为 “false”,则原生库以未压缩的形式存储在 APK 中。虽然您的 APK 可能较大,但应用应该加载得更快,因为库是在应用运行时直接从 APK 加载。

  首先第一句,此属性指示软件包安装程序是否将原生库从 APK 提取到文件系统。,说明当该值设置为false时,apk在安装后不会将lib中的SO文件提取到安装目录,这样的好处在于同样的SO文件不会出现两份,节约空间。

  第二句和第三句,如果设置为false,apk中的SO文件在打包时将会以未压缩的形式出现,这样系统在加载APK的同时也会将SO文件映射到内存中而无需进行解压缩,提高加载速度;同时由于SO文件未被压缩所以会导致安装包的尺寸会变大。

010_elf_header

010_no_elf_header

  总结一下,根据extractNativeLibs的值的不同进行对比,总体来说利大于弊:

extractNativeLibs True False
是否压缩SO文件 True False
安装后是否提取SO文件 True False
安装包大小
加载速度

extractNativeLibs的默认值

  同样来自官方描述

extractNativeLibs 的默认值取决于 minSdkVersion 和您使用的 AGP 版本。在大多数情况下,默认行为很可能符合您的预期,您无需显式设置此属性。

  可以知道extractNativeLibs在打包时的默认值是会由打包工具自动根据情况设定的,比如我在compileSdk 31; minSdk 23; targetSdk 31的情况下,extractNativeLibs的默认值可能就是false

extractNativeLibs的使用

  想要对extractNativeLibs的值进行设置主要有两种方式,第一种就是直接修改AndroidManifest.xml即可。第二种看官方描述:

从 AGP 4.2.0 开始,extractNativeLibs 清单属性已被 DSL 选项 useLegacyPackaging 取代。 您应该使用应用的 build.gradle 文件中的 useLegacyPackaging(而非清单文件中的 extractNativeLibs)来配置原生库压缩行为。如需了解详情,请参阅版本说明使用 DSL 打包压缩的原生库。

我们建议以未压缩的形式打包原生库,因为这会减小应用安装大小,缩减应用下载大小,并缩短用户的应用加载时间。不过,如果您希望 Android Gradle 插件在构建应用时打包压缩后的原生库,请在应用的 build.gradle 文件中将 useLegacyPackaging 设置为 true:

android {
    packagingOptions {
        jniLibs {
            useLegacyPackaging true
        }
    }
}

实际上两种方式最终的结果都是修改了打包后的apk中AndroidManifest.xml中的对应字段值。

extractNativeLibs对逆向的影响

PatchSo

  在逆向中很常用的一个技巧就是对apk安装后的so文件进行patch然后替换原来的so文件,这样可以绕过签名校验。这种方式的前提是extractNativeLibs必须为true,否则在apk安装目录下并不会找到任何的so文件可以让我们进行patch。

重打包

  一个apk如果它的extractNativeLibs设置为false,那么如果我们直接对apk重打包并签名是无法安装的,会出现如下报错:

Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries,res=-2]

原因是重打包后的apk必须要进行对齐。参考Java Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2]

官方说明如下:

注意:如果您在使用 apksigner 为 APK 签名后又对 APK 做了更改,则 APK 的签名将会失效。因此,要使用 zipalign 等工具,您必须在为 APK 签名之前使用。

我们需要用zipalign进行对齐,并且必须要在使用apksigner进行签名之前对齐。


文章作者: 大A
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 大A !
评论
  目录