一、 加密不侵入 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
替换进度如下 :

ContextImplprivate 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);