关于MultiDex

0x00背景

–在逆向分析apk的过程中,会发现里面会出现多个dex的情况。

一个正常APK文件通常包含以下文件:

classes.dex: Dalvik字节码,可被Dalvik虚拟机执行。
AndroidManifest.xml: 一个的Android清单文件,用于描述该应用程序的名字、版本号、所需权限、注册的服务、链接的其他应用程序。该文件使用XML文件格式。
META-INF 文件夹: 下面有3个文件
MANIFEST.MF: 清单信息
CERT.RSA: 保存应用程序的证书和授权信息
CERT.SF: 保存SHA-1信息资源列表
res: APK所需要的资源文件夹
assets: 不需编译的原始资源文件目录
resources.arsc:编译后的二进制资源文件
lib:库文件目录

如果是这种:
|—classes.dex
|—classes.dex
哈哈,恭喜你 你找到利用masterkey 漏洞的样本了;
漏洞详情见:http://www.vuln.cn/6043(乌云,乌云快回来~~~)

如果是这种
|—classes.dex
|—classes2.dex
|—classes3.dex
那么就是MultiDex了

0x01原因分析

引入MultiDex的缘由:Android系统单个DEX文件可被引用的方法总数(自己开发的代码以及所引用的Android框架、类库的代码)被限制为65536,如果大于则安装失败。
随着业务规模发展到一定程度,不断地加入新功能、添加新的类库,代码在急剧的膨胀。轻松的久突破了这个限制。

那么怎么解决这一问题呢?

首先使用Android SDK Manager升级到最新的Android SDK Build Tools和Android Support Library。然后进行以下两步操作:

1.修改Gradle配置文件,启用MultiDex并包含MultiDex支持:

  android {
    compileSdkVersion 21 buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling MultiDex support.
        MultiDexEnabled true
        }
        ...
    }
    dependencies { compile 'com.android.support:MultiDex:1.0.0'
}

2.让应用支持多DEX文件。在官方文档中描述了三种可选方法:

1.在AndroidManifest.xml的application中声明android.support.MultiDex.MultiDexApplication;
2.如果你已经有自己的Application类,让其继承MultiDexApplication;
3.如果你的Application类已经继承自其它类,你不想/能修改它,那么可以重写attachBaseContext()方法:

@Override 
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

并在Manifest中添加以下声明:

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.MultiDex.myapplication">
        <application
        ...
        android:name="android.support.MultiDex.MultiDexApplication">
        ...
        </application>
    </manifest>

如果你只是想试验,那么可以使用强制分包,或者改最小的方法数目:
可以在生成DEX文件的这一步中, 在Ant或gradle中自定义一个Task来干预DEX产生的过程,从而产生多个DEX,下图是在ant和gradle中干预产生DEX的自定task的截图:

tasks.whenTaskAdded { task ->
    if (task.name.startsWith('proguard') && (task.name.endsWith('Debug') || task.name.endsWith('Release'))) {
        task.doLast {
            makeDexFileAfterProguardJar();
        }
        task.doFirst {
            delete "${project.buildDir}/intermediates/classes-proguard";

            String flavor = task.name.substring('proguard'.length(), task.name.lastIndexOf(task.name.endsWith('Debug') ? "Debug" : "Release"));
            generateMainIndexKeepList(flavor.toLowerCase());
        }
    } else if (task.name.startsWith('zipalign') && (task.name.endsWith('Debug') || task.name.endsWith('Release'))) {
        task.doFirst {
            ensureMultiDexInApk();
        }
    }
}

系统如何加载MultiDex

第一步打开apk这个zip包

第二步把MultiDex的dex解压出来(除去Classes.dex之外的其他DEX,例如:classes2.dex, classes3.dex等等),因为android系统在启动app时只加载了第一个Classes.dex,其他的DEX需要我们人工进行安装——main方法等主启动项一定要在Classes.dex里

第三步通过反射进行安装,这三步其实都比较耗时, 为了解决这个问题我们考虑是否可以把DEX的加载放到一个异步线程中,这样冷启动速度能提高不少,同时能够减少冷启动过程中的ANR

dex在classloader加载的过程中会变身为odex;

dexopt优化

5.0之后会有dex2ort

参考:
http://www.vuln.cn/6043
http://tech.meituan.com/mt-android-auto-split-dex.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值