Skip to main content

安卓 APK/AAB 保护指引

安卓应用的安全性问题#

二次打包风险#

安卓原生应用一般使用 Java/Kotlin 语言编写,编译打包后生成Dex文件存放在APK中。Dex文件包含了类、方法、成员等信息,甚至包含了源文件名,使用jadx/jd-gui等工具可以轻松反编译出源代码。代码被反编译后,可以很容易使用apktool等工具修改代码,破解应用或者植入广告,再重新打包发布。

dex-decompile

代码和资源易被窃取#

由于Dex文件可以完整地反编译出源代码,未经保护的代码发布后与开源无异,可能会被竞争对手无成本地直接窃取使用,包内的音视频和图片等资源文件也容易被直接窃取使用,严重损害开发者利益。

Virbox Protector功能介绍#

Virbox Protector对APK和AAB程序提供了运行时自保护、防逆向、防篡改、代码和资源加密等功能,全方位保护APK和AAB程序。

APK

运行时自保护#

运行时自保护,是在应用启动时保护自身,防止应用被恶意调试分析、动态注入,防止在一些开启了高权限的自定义设备或模拟器中运行,进而破解应用程序的行为。

功能描述
防调试防止应用被 IDA Pro,gdb,lldb,jeb 等工具调试,检测到被调试后退出。
防注入防止应用被 ptrace 附加,so 库注入,检测 xposed 等 hook 框架。
模拟器检测检测到应用在模拟器中运行时退出。
Root 检测检测到应用在 Root 环境下运行时退出。
多开检测检测到应用多开(分身)时退出。
代理检测检测到APP使用代理时退出。
vpn检测检测当前环境开启VPN时退出。

防逆向#

防止应用中的 Dex、SO库、脚本语言代码被反编译或窃取,防止逆向分析。

功能描述
Dex 加密加密并隐藏 APK 中的所有 Dex 文件,防止 jadx, jeb 等工具反编译。
Dex 虚拟化对指定的 Dex 中的方法进行虚拟化保护,将代码转换成自定义的 Native 层虚拟机中执行,可以防止一切内存截取方式还原代码。
资源加密加密 apk 中的资源、脚本等文件,防止资源被提取。
SO 库保护对 apk 中指定的 so 库保护,加密代码段,防止 IDA Pro 等工具反汇编、反编译。
SO 库保护(隐藏符号表)隐藏 SO 库中的导出函数、加密 SO 库中的 ELF 重定位,防止脱壳。

Dex 虚拟化效果

保护前:

dex_origin

保护后:

dex_vm_after

保护后跳转到自定义的解释器中执行(见上图 vm_void 方法)。

防篡改#

运行时校验代码及应用的完整性,防止应用被篡改,防止二次打包。

功能描述
签名校验校验 APK 中的开发者签名,防止 APK 被第三方二次打包重签名。
文件校验校验 APK 中的资源、脚本、SO 库等文件,防止 APK 中的文件被篡改进行二次打包。

支持范围#

操作系统和架构兼容性#

  • 支持 Android 4.0 以上系统
  • 支持 arm32/arm64/x86/x64 架构

保护指引#

保护前的准备#

JDK配置#

对APK/AAB签名,需要用到jdk中的 jarsigner工具(位于jdk bin目录)和 java命令,Windows平台需要将jdk的 bin目录加入环境变量,Linux/macOS 一般安装jdk后即可直接调用。

配置完毕后,在命令行终端下输入 jarsigner即可验证环境是否生效。

生成 Keystore#

如果开发者尚未生成 Keystore,可以安装 jdk 后手动生成,生成命令如下:

keytool -genkeypair -keyalg RSA -keysize 1024 -sigalg SHA256withRSA -validity <validity_days> -alias <key_alias> -storepass <ks_pass> -keystore <keystore_path>

生成Keystore需要记录KeyStore路径KeyStore密钥密钥别名别名密码,在保护过程中的签名设置里需要填写。

举例:

# -validity    :有效期天数,这里随便填写个足够长的数据即可# -keystore    :KeyStore路径# -storepass   :KeyStore密码# -alias       :密钥别名# (别名密码可以在执行命令后的交互提示中填写)
keytool -genkeypair -keyalg RSA -keysize 1024 -sigalg SHA256withRSA -validity 500000 -alias MyCert -storepass MyCert.jks

反编译工具推荐#

反编译工具可以用于保护效果的评估。

对于APK中的 Java/Kotlin代码部分,推荐使用免费开源 Jadx:

Jadx 下载地址: Releases · skylot/jadx · GitHub

对 APK包的中 Native库,推荐使用 IDA Pro(收费),或 Ghidra(免费开源):

Ghidra 下载地址: Releases · NationalSecurityAgency/ghidra (github.com)

常规的保护方式#

Virbox Protector 的默认选项,可以防止程序被反编译、防资源窃取、防脱壳、防逆向、防二次打包等。一般可以满足大部分的安全性需求,以下是APK和AAB程序的保护选项和推荐。

功能保护建议保护效果
Dex 加密勾选加密隐藏Dex文件,防止反编译
文件校验勾选校验APK包内除签名信息外的所有文件,防止被篡改
签名校验APK格式勾选;AAB格式如果由Google管理证书请勿勾选校验开发者签名,防止被第三方重签名打包
反注入勾选防止内存Dump,防止调试器附加
调试器检测勾选检测到调试器调试,则退出进程
模拟器检测按需选择检测到运行环境为模拟器,则退出进程
Root检测按需选择检测到运行环境为Root环境,则退出进程
多开检测按需选择检测到运行环境为手机分身或应用分身,则退出进程
[V] 代码虚拟化

函数选项

Virbox Protector 默认会将入口Application和Activity类中的方法虚拟化,防止代码被还原脱壳,建议使用默认。

资源加密

按需选择是否加密。

SO库保护

按需选择是否保护,保护后可以防止反编译。

自定义虚拟化#

Virbox Protector 会默认对App 入口类和Activity类虚拟化保护,也支持自由选择类方法进行虚拟化保护,保护关键代码逻辑,用于应对高安全性的保护场景。

代码虚拟化,是将函数原本的汇编指令,转换自定义的虚拟机指令。函数被虚拟化保护后,运行时内存中不会出现原始字节码,而是以伪代码的形式出现,由自定义的解释器解释执行,安全性极高。如果一个加密方案可以逼迫破解者去分析虚拟化的代码,说明这个方案是非常成功的,需要分析的代码(破解点)越多,破解的难度就越大

代码虚拟化对程序的性能影响较大,不可大面积使用,常用于以下几类函数:

  • 对安全性要求较高的一些自定义算法。
  • 可能被篡改或者逆向的函数(如关键的授权验证逻辑、协议封装加密逻辑)。

自动化集成#

命令行工具#

Virbox Protector 的命令行工具 virboxprotector_con 的默认路径位于:

Windows:C:\Program Files\senseshield\Virbox Protector 3\bin
Linux:/usr/share/virboxprotector/bin
macOS:/Applications/Virbox Protector 3.app/Contents/MacOS/bin

使用配置文件保护#

使用工具界面进行保护,在被保护的程序旁边会生成 .ssp 文件,然后调用virboxprotector_con

virboxprotector_con <input_file> -o <output_file>

virboxprotector_con 会自动查找 <input_file>.ssp 作为配置文件开始保护。

无配置文件保护#

如果没有配置文件,virboxprotector_con会使用默认参数保护,可以传入具体参数覆盖默认选项,参考命令行选项

命令行选项#

保护选项#

选项命令行默认选项
Dex 加密--dex-enc=APK:1, AAB:0
字符串加密--str-enc=0
文件校验--file-check=1
签名校验(APK)--sign-check=0
反注入--anti-inject=1
内存保护--mem-protect=0
防截屏--anti-screenshot=0
调试器检测--detect-dbg=1
模拟器检测--detect-emu=0
Root检测--detect-root=0
多开检测--detect-multi=0
代理检测--detect-proxy=0
VPN检测--detect-vpn=0
输出 apks (AAB启用签名时生效)--apks=<apks_path>N/A

函数选项#

选项命令行
代码虚拟化-v

支持指定函数名称或规则保护,使用 ;号隔开,支持通配符 *,举例:

-v "class1.method2;class2.*"

资源加密#

使用 --res-enc=1 开启资源加密,资源列表使用 ; 隔开,支持通配符 *

选项命令行默认选项
启用--res-enc=0
资源列表-res <resource_list>默认所有资源
移除不保护的资源文件--exclude-res=<exclude_list>N/A

举例:

保护指定的资源:--res-enc=1 -res "file1;file2;assets/file1;assets2/*"保护所有的资源:--res-enc=1 -res "*"

SO库保护#

选项命令行默认选项
隐藏符号表--hide-symtab=0
资源列表-lib <nativelib_list>N/A
移除不保护的so库--exclude-lib=<exclude_list>N/A

举例:

保护指定目录下的so库:--hide-symtab=0 -lib "lib/armeabi-v7a/libhello.so;/lib/arm64-v8a/*"保护所有的so库:--hide-symtab=0 -lib "*"

命令行保护举例#

对 APK 进行保护,开启部分功能并设置签名:

virboxprotector_con app-release.apk     --dex-enc=1 --file-check=1 --detect-dbg=1 --sign-check=1    --res-enc=1 -res "assets/*"    --hide-symtab=0 -lib "lib/armeabi-v7a/libhello.so;/lib/arm64-v8a/*"    --sign=1 --ks="test/android.ks" --ks-pass=mypass --ks-key-alias=CERT --key-pass=mykeypass    -o app-release-protected.apk

问题#

1.Linux系统上使用命令行不加双引号不会生效么?

答:是的,Linux系统上使用命令行保护时参数后面需要加"",则参数功能才会生效。

2.命令行对资源文件保护时使用"*"文件,则默认保护哪些文件?

普通apk,默认保护assets和res/layout目录下的资源;

普通aab,默认保护base/assets目录下的资源;

Unity apk,默认保护assets目录下的资源;

Unity aab,默认保护base/assets目录下的资源。

3.加壳工具不支持Android资源文件读取视频的方式包括有?

1)使用了系统 自带的media player服务播放的音频 2)自己解析apk读取的资源