文章目录
- 一、创建用户自定义 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);