一、 加密不侵入 Application 原则
在开发时 , 希望 不侵入 Application , 不侵入原来的应用 ; 这里就需要涉及到将 代理 Application 替换成真实的 Application ;
代理 Application 的作用是对 真实的 Application 所在的 DEX 文件进行解密 , 创建真实的 Application , 并且将真实的 Application 设置到应用中 ;
需要替换的 Application 的位置以及如何获取被替换的成员 : 【Android 安全】DEX 加密 ( Application 替换 | 判定自定义 Application 存在 | 获取 ContextImpl 对象 ) ;
这样就可以实现不用特意修改 Application , 就实现了加密操作 ;
上一篇博客 【Android 安全】DEX 加密 ( Application 替换 | 创建用户自定义 Application | 替换 ContextImpl 对象的 mOuterContext 成员 ) 创建了用户自定义的 Application , 然后替换了 ContextImpl 对象的 mOuterContext 成员 ;
本博客继续完成后续操作 ;
截止到此处, Application 创建完毕 , 下面开始逐个替换下面的 Application
替换进度如下 :
① ContextImpl 的 private Context mOuterContext 成员是 kim.hsl.multipledex.ProxyApplication 对象 ; ( 已完成 )
② ActivityThread 中的 Application mInitialApplication 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
③ ActivityThread 中的 ArrayList<Application> mAllApplications 集合中添加了 kim.hsl.multipledex.ProxyApplication 对象 ;
④ LoadedApk 中的 mApplication 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
二、 替换 ActivityThread 中的 Application mInitialApplication 成员
替换 ActivityThread 中的 Application mInitialApplication 成员 , 当前成员是 kim.hsl.multipledex.ProxyApplication 对象 , 需要替换成用户自定义的 Application 对象 ;
首先获取 的 mInitialApplication 成员字段 , 获取 ActivityThread 中的 mInitialApplication 成员 , 注意 mInitialApplication 成员是私有的 , 设置可访问性 ;
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
// 获取 ActivityThread 中的 mInitialApplication 成员
Field mInitialApplicationField =
activityThreadClass.getDeclaredField("mInitialApplication");
// mInitialApplication 成员是私有的 , 设置可访问性
mInitialApplicationField.setAccessible(true);
然后获取 ActivityThread 对象 , 从 ContextImpl 对象中获取其 ActivityThread mMainThread 成员变量 , ContextImpl 就是本应用的上下文对象 , 调用 getBaseContext 方法获得 ;
// 从 ContextImpl 对象中获取其 ActivityThread mMainThread 成员变量
Field mMainThreadField = contextImplClass.getDeclaredField("mMainThread");
mMainThreadField.setAccessible(true);
// ContextImpl 就是本应用的上下文对象 , 调用 getBaseContext 方法获得
Object mMainThread = mMainThreadField.get(baseContext);
最后替换该成员 , 其中 ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可 ;
// ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可
mInitialApplicationField.set(mMainThread, delegate);
该步骤的完整代码 :
// II . 替换 ④ ActivityThread 中的 Application mInitialApplication
// 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
// 获取 ActivityThread 中的 mInitialApplication 成员
Field mInitialApplicationField =
activityThreadClass.getDeclaredField("mInitialApplication");
// mInitialApplication 成员是私有的 , 设置可访问性
mInitialApplicationField.setAccessible(true);
// 从 ContextImpl 对象中获取其 ActivityThread mMainThread 成员变量
Field mMainThreadField = contextImplClass.getDeclaredField("mMainThread");
mMainThreadField.setAccessible(true);
// ContextImpl 就是本应用的上下文对象 , 调用 getBaseContext 方法获得
Object mMainThread = mMainThreadField.get(baseContext);
// ContextImpl 就是应用的 Context , 直接通过 getBaseContext() 获取即可
mInitialApplicationField.set(mMainThread, delegate);