文章目录
一、创建用户自定义 Application
二、替换 ContextImpl 对象的 mOuterContext 成员
dex 解密时 , 需要将 代理 Application 替换为 真实 Application ; 替换 Application 首先要理解系统如何注册应用的 Application 的 ;
上一篇博客 【Android 安全】DEX 加密 ( Application 替换 | 判定自定义 Application 存在 | 获取 ContextImpl 对象 ) , 继续后续步骤 ;
一、创建用户自定义 Application
获取 app_name 元数据 , 该元数据就是用户自定义的 Application 的全类型 , 即 包名.类名 , 这里是 kim.hsl.dex.MyApplication ;
通过 反射 获取 Application 类 , 系统也是进行的反射操作 , 并创建用户真实配置的 Application ;
// 通过反射获取 Application , 系统也是进行的反射操作 Class<?> delegateClass = Class.forName(app_name); // 创建用户真实配置的 Application Application delegate = (Application) delegateClass.newInstance();
调用 Application 的 attach 函数 , 该函数无法直接调用 , 也需要通过反射调用 , 该方法是私有的 , 需要 设置 attach 方法允许访问 ;
// 调用 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 对象 ;
// 获取上下文对象 , // 该 Context 是通过调用 Application 的 attachBaseContext 方法传入的 ContextImpl // 将该上下文对象传入 Application 的 attach 方法中 attach.invoke(delegate, baseContext);
本步骤完整代码示例 :
// 获取上下文对象 , 保存下来 , 之后要使用 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 类 ,
Class<?> contextImplClass = Class.forName("android.app.ContextImpl");
然后获取类成员 mOuterContext 字段 ,
// 获取 ContextImpl 中的 mOuterContext 成员 Field mOuterContextField = contextImplClass.getDeclaredField("mOuterContext");
设置反射中私有成员的可访问性 ,
// mOuterContext 成员是私有的 , 设置可访问性 mOuterContextField.setAccessible(true);
ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可 ,
// ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可 mOuterContextField.set(baseContext, delegate);
本步骤完整代码 :
// 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);