【Android 安全】DEX 加密 ( Application 替换 | 创建用户自定义 Application | 替换 ContextImpl 对象的 mOuterContext 成员 )

2023-03-28 20:22:46 浏览数 (1)

文章目录

  • 一、创建用户自定义 Application
  • 二、替换 ContextImpl 对象的 mOuterContext 成员

dex 解密时 , 需要将 代理 Application 替换为 真实 Application ; 替换 Application 首先要理解系统如何注册应用的 Application 的 ;

上一篇博客 【Android 安全】DEX 加密 ( Application 替换 | 判定自定义 Application 存在 | 获取 ContextImpl 对象 ) , 继续后续步骤 ;

一、创建用户自定义 Application


获取 app_name 元数据 , 该元数据就是用户自定义的 Application 的全类型 , 即 包名.类名 , 这里是 kim.hsl.dex.MyApplication ;

通过 反射 获取 Application 类 , 系统也是进行的反射操作 , 并创建用户真实配置的 Application ;

代码语言:javascript复制
            // 通过反射获取 Application , 系统也是进行的反射操作
            Class<?> delegateClass = Class.forName(app_name);

            // 创建用户真实配置的 Application
            Application delegate = (Application) delegateClass.newInstance();

调用 Application 的 attach 函数 , 该函数无法直接调用 , 也需要通过反射调用 , 该方法是私有的 , 需要 设置 attach 方法允许访问 ;

代码语言:javascript复制
            // 调用 Application 的 attach 函数
            // 该函数无法直接调用 , 也需要通过反射调用
            // 这里先通过反射获取 Application 的 attach 函数
            Method attach = Application.class.getDeclaredMethod("attach", Context.class);
            // attach 方法是私有的 , 设置 attach 方法允许访问
            attach.setAccessible(true);

attach 方法需要传入两个参数 , Application 对象 和 Context 对象 ,

该 Context 是通过调用 Application 的 attachBaseContext 方法传入的 ContextImpl , 因此通过调用 getBaseContext() 方法即可获取 Context 对象 ;

将上面 delegateClass.newInstance() 创建的 Application 对象 , 和 getBaseContext() 获取的 Context 对象 , 传入 attach 方法中 , 即可创建完整的 Application 对象 ;

代码语言:javascript复制
            // 获取上下文对象 ,
            // 该 Context 是通过调用 Application 的 attachBaseContext 方法传入的 ContextImpl
            // 将该上下文对象传入 Application 的 attach 方法中
            attach.invoke(delegate, baseContext);

本步骤完整代码示例 :

代码语言:javascript复制
            // 获取上下文对象 , 保存下来 , 之后要使用
            Context baseContext = getBaseContext();

            // 通过反射获取 Application , 系统也是进行的反射操作
            Class<?> delegateClass = Class.forName(app_name);

            // 创建用户真实配置的 Application
            Application delegate = (Application) delegateClass.newInstance();

            // 调用 Application 的 attach 函数
            // 该函数无法直接调用 , 也需要通过反射调用
            // 这里先通过反射获取 Application 的 attach 函数
            Method attach = Application.class.getDeclaredMethod("attach", Context.class);
            // attach 方法是私有的 , 设置 attach 方法允许访问
            attach.setAccessible(true);

            // 获取上下文对象 ,
            // 该 Context 是通过调用 Application 的 attachBaseContext 方法传入的 ContextImpl
            // 将该上下文对象传入 Application 的 attach 方法中
            attach.invoke(delegate, baseContext);

二、替换 ContextImpl 对象的 mOuterContext 成员


ContextImpl 的 private Context mOuterContext 成员是 kim.hsl.multipledex.ProxyApplication 对象 , 这是外层的壳 Application , 现在替换成上面创建的用户自定义的 kim.hsl.dex.MyApplication 对象 ;

首先通过反射获取 ContextImpl 类 ,

代码语言:javascript复制
            Class<?> contextImplClass = Class.forName("android.app.ContextImpl");

然后获取类成员 mOuterContext 字段 ,

代码语言:javascript复制
            // 获取 ContextImpl 中的 mOuterContext 成员
            Field mOuterContextField = contextImplClass.getDeclaredField("mOuterContext");

设置反射中私有成员的可访问性 ,

代码语言:javascript复制
            // mOuterContext 成员是私有的 , 设置可访问性
            mOuterContextField.setAccessible(true);

ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可 ,

代码语言:javascript复制
            // ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可
            mOuterContextField.set(baseContext, delegate);

本步骤完整代码 :

代码语言:javascript复制
            // I . 替换 ① ContextImpl 的 private Context mOuterContext
            //  成员是 kim.hsl.multipledex.ProxyApplication 对象
            Class<?> contextImplClass = Class.forName("android.app.ContextImpl");
            // 获取 ContextImpl 中的 mOuterContext 成员
            Field mOuterContextField = contextImplClass.getDeclaredField("mOuterContext");
            // mOuterContext 成员是私有的 , 设置可访问性
            mOuterContextField.setAccessible(true);
            // ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可
            mOuterContextField.set(baseContext, delegate);

0 人点赞