Android SDK安全加固问题与分析

文章介绍了在Android环境下,为保护应用程序安全,尤其是dex文件,采用的加固技术演进,包括动态加载、Hook、指令抽取、java2cpp,最终重点讨论了VMP(VirtualMachineProtection)技术的工作原理、实现步骤和其在提高代码保护安全性上的优势。同时,文章提到了加固技术面临的兼容性和性能挑战,并给出了优化建议。
摘要由CSDN通过智能技术生成

作者 | 百度APP技术平台

导读

在移动互联网快速发展的背景下,保护Android应用程序的安全性和知识产权变得尤为重要。为了防止恶意攻击和未授权访问,通常采用对dex文件进行代码加固来保护应用程序。随着Android加固技术经过动态加载、不落地加载、指令抽取、java2cpp、VMP等技术不断演进和改进,VMP加固技术成为一种高安全性解决方案。因此,本文将着重介绍一种实现和落地VMP技术的思路,以帮助大家了解其工作原理和应用场景。

全文8359字,预计阅读时间21分钟。

01 问题背景

在移动互联网快速发展的背景下,Android 作为全球最受欢迎的移动操作系统,吸引了大量开发者和用户。随着应用市场的竞争加剧,保护应用程序的安全性和知识产权变得越来越重要。

同时,随着公司业务的发展,百度与外部友商深度合作,需要对外输出了百度业务能力SDK。在这种背景下,对Android代码进行加固成为了一种必要的安全措施。加固可以提高应用程序的安全性,保护知识产权,防止逆向工程和破解。

02 问题分析

Android 应用程序是由 Java/Kotlin 语言编写而成,然后打包成 APK 文件。Java 代码被编译成 APK/AAR 中的 dex 文件,dalvik/art 虚拟机解释执行 dex 中的字节码。攻击者可以使用反编译工具很容易的逆向分析 dex 文件,理解代码关键逻辑,增加恶意代码,再打包回 APK 文件。

可以看到,dex 文件就是代码加固的保护核心!

03 加固调研

为了解决对 dex文件的代码加固,我们进行了相关技术调研,其实在Android代码安全领域,相关技术一直属于不断攻防演进的过程。如下是业界常用的加固技术方案:比如最初的360加固给APK加壳,通过不落地动态加载实现加固;市场上常用的类方法抽取指令加固;以及将java方法转native方法jni调用等。

3.1 DexClassLoader 动态加载机制

图片

利用 Android 系统的 DexClassLoader 动态加载机制,通过将保护的 dex 文件解压解密后,动态加载到内存中执行。

这种方式有效地抵御了 APK 文件的静态分析,使得逆向分析者无法在 APK 文件中找到真实的 dex 文件。但是由于动态加载技术主要依赖于java的动态加载机制,所以要求关键逻辑部分必须进行解压,并且释放到文件系统。

这种动态加载技术不足之处在于:1.这一解压释放机制就给攻击者留下直接获取对应文件的机会; 2.可以通过hook虚拟机关键函数,进行dump出原始的dex文件数据。

3.2 Hook 技术

针对 DexClassLoader 动态加载机制的保护缺陷,采用 Hook 技术来解决问题。

在动态加载过程中,通过替换 DexClassLoader 执行过程中的 dex 内存,将其替换为真实 dex 文件的内存,从而实现了无需将 dex 落地的加载方式。

然而,dex 文件虽然不会解密并保存到文件系统,但它在内存中是完整存在的。因此,在应用程序运行后,逆向分析者可以通过内存搜索的方式将 dex 文件转储出来。

3.3 指令抽取

为了对抗逆向开发通过内存搜索的方式将 dex 文件转储出来,加固技术采用了函数抽取的方法,使得 dex 文件在内存中一直处于不完整的状态。

其实现思路大致如下:

1、对要保护的 dex 文件进行预处理,将需要保护的函数指令抽取出来并进行加密存储,同时在原位置填充 nop 指令。

2、当 dalvik/art 执行到抽取的函数时,利用 hook 技术拦截 libdalvik.so/libart.so 中的指令读取部分,将函数对应的真实指令解密并填充,使得 dalvik/art 能够继续解释执行。

随着逆向技术的不断发展,改造 dalvik 并遍历所有 dex 方法,以及内存重组 dex,成为了对抗此种加固保护的有效方法。其中,dexhunter 是该领域的主要代表之一。

3.4 java2cpp 技术

随着内存脱壳机的出现,指令抽取的保护方式逐渐失去有效性。为了应对这一问题,java2cpp 技术开始被引入到加固保护中。

核心是对 dex 中的函数进行处理,将函数中的 dalvik 指令转换成等效的 cpp 代码(基于 JNI),然后编译成本地的动态链接库(native so 库),并将保护的方法标记为 native 属性。这样,在执行到受保护的方法时,执行流会转移到本地层执行对应的 cpp 代码。

比如原函数:

public class HelloVMP2 {
    public int compute(int a, int b) {
        int c = a + a;
        int d = a * b;
        int e = a - b;
        int f = a / b;
        int result = c + d + e + f;
        return result;
    }
}

转换后:

public class HelloVMP2 {

    static {
        System.loadLibrary("hello_vmp2");
    }

    public native int compute(int a, int b);
}

extern "C" JNIEXPORT jint JNICALL
Java_com_vmp_mylibrary_HelloVMP2_compute(JNIEnv* env, jobject obj, jint a, jint b) {
    jint c = a + a;
    jint d = a * b;
    jint e = a - b;
    jint f = a / b;
    jint result = c + d + e + f;
    return result;
}

这种方式下,仅将 java 转 cpp 编译成动态链接库,但是so代码依然可以被破解,在此基础上其实还是可以继续提高代码保护的安全性,那就是 DEX-VMP 技术。

3.5 DEX-VMP

DEX-VMP 原理理解起来比较容易,其针对的保护单位也是函

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>