ArturoYi
hidden-dex-minidemo 把业务实现编成加密 DEX。运行时由 so 解密后在内存里加载。主 DEX 只保留公开接口。

hidden-dex-minidemo 隐藏的是 自管理来电实现,不是整个 App。宿主只依赖公开 SDK。真正的 HiddenLandingPage 在构建期打成加密 DEX,放入 AAR 的 assets/。进程启动后,由 libhiddendecrypt.so 解密,并在内存里加载。

这只能提高静态分析成本,并不能彻底防止反编译。so 仍可被 hook,密钥仍须由接入方保管。用 JADX 打开主 DEX,只能看到 HiddenSdk.invoke(Int, Any?, Any?)。

下载示例

可运行工程与本文档对应,归在 Android 分类。解压后用 Android Studio 打开。

hidden-dex-minidemo

Android

把业务实现编成加密 DEX。运行时由 so 解密后在内存里加载。主 DEX 只保留公开接口。

hidden-dex-minidemo.zip · 139 KB

产物如何拆分

接入方拿到的 AAR:

hidden-sdk-1.0.0.aar
├── classes.jar
│   ├── HiddenSdk
│   └── HiddenInitResult
├── jni/*/libhiddendecrypt.so
├── assets/payload/hidden.dex.enc
└── proguard.txt

公开接口只剩:

object HiddenSdk {
    fun init(context: Context, payloadKey: String?): HiddenInitResult
    fun invoke(op: Int, a: Any? = null, b: Any? = null): Any?
}

:hidden-landing-page 只在 SDK 仓库里编 jar → d8 → AES-256-GCM,不要给宿主 implementation。

模块给接入方吗进主 DEX?
:hidden-sdk只交付这个 AAR接口、JNI、KeepAlive 占位类
:hidden-landing-page不交付否,只进加密 payload
:app不发布权限、清单占位、Compose 页

十种加固方式

安卓代码加固(1):加密DEX
构建期把 landing-page 打成 AES-256-GCM 密文,文件头为 HDX1。
安卓代码加固(2):Native解密
自实现 AES-GCM 在 so 里运行,Java 不接触明文 DEX。
安卓代码加固(3):内存加载
InMemoryDexClassLoader 接收 ByteBuffer,不落明文文件。
安卓代码加固(4):指令分发
公开入口只有 invoke(op),对照表不进入 AAR。
安卓代码加固(5):XOR混淆
资源路径、类名、方法名在 so 里按 0x5A 异或。
安卓代码加固(6):密钥外置
AAR 不带密钥。CI 用环境变量,本地用 gitignore 文件。
安卓代码加固(7):依赖隔离
compileOnly 加解析期检查,禁止明文 class 进入 APK。
安卓代码加固(8):构建校验
AAR、APK、源码三道检查,漏依赖则无法通过编译。
安卓代码加固(9):防录屏
FLAG_SECURE。未 init 也会给当前页加上该标志。
安卓代码加固(10):ABI门禁
so 与加密实现约定版本 12,对不上就拒绝加载。

运行时序

宿主先 init

Application.onCreate 传入 64 个 hex 字符。密钥为空则直接失败,不读取 assets。

so 读密文

AAssetManager 打开 XOR 后的路径 payload/hidden.dex.enc。

AES-GCM 解密

校验 HDX1 头和 GCM tag。明文必须以 dex 开头。

内存里 loadClass

InMemoryDexClassLoader 加载 XOR 后的 HiddenLandingPage,并核对 ABI。

invoke 分发

Java 只传整数指令,native 再通过 GetMethodID 调用实现。

可读的方法名应放在宿主自己的包装里,例如 Demo 的 HostBridge。不要把对照表写进 SDK 源码。

下一步

Copyright © 2026