文章目录
一、ActivityThread 后续分析
二、ActivityThread 相关源码
三、Application 替换位置
dex 解密时 , 需要将 代理 Application 替换为 真实 Application ; 替换 Application 首先要理解系统如何注册应用的 Application 的 ;
一、ActivityThread 后续分析
在 【Android 安全】DEX 加密 ( Application 替换 | Android 应用启动原理 | ActivityThread 源码分析 ) 基础上 , 继续分析 ActivityThread 的 handleBindApplication 方法 ;
在 Application app = data.info.makeApplication(data.restrictedBackupMode, null) 代码中 , 创建了 Application , 并且调用了 Application 的 attachBaseContext 方法 ;
创建完毕之后 , 将创建的 Application 赋值给了 ActivityThread 的 mInitialApplication 成员 , mInitialApplication = app ;
④ ActivityThread 的 mInitialApplication 成员是 Application
在后面调用了 mInstrumentation.callApplicationOnCreate(app) 方法 , 执行了 Application 中的 onCreate 方法 , 此时
try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } }
二、ActivityThread 相关源码
public final class ActivityThread { Application mInitialApplication; final ArrayList<Application> mAllApplications = new ArrayList<Application>(); final ApplicationThread mAppThread = new ApplicationThread(); final Looper mLooper = Looper.myLooper(); final H mH = new H(); private class H extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } } private void handleBindApplication(AppBindData data) { try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { // 此处调用了 Application 的 onCreate 函数 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { StrictMode.setThreadPolicy(savedPolicy); } } public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) { sendMessage(H.BIND_APPLICATION, data); } private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. } } public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); Looper.loop(); } }
完整源码参考 : 6.0.1_r16/xref/frameworks/base/core/java/android/app/ActivityThread.java
三、Application 替换位置
当应用启动后 , 在 AndroidManifest.xml 中配置的 代理 Application 为 kim.hsl.multipledex.ProxyApplication ;
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="kim.hsl.dex"> <application android:name="kim.hsl.multipledex.ProxyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- app_name 值是该应用的 Application 的真实全类名 --> <meta-data android:name="app_name" android:value="kim.hsl.multipledex.ProxyApplication"/> <!-- DEX 解密之后的目录名称 --> <meta-data android:name="app_version" android:value="1.0"/> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
因此在应用程序开始运行时 , 以下几个位置运行的 Application 是 kim.hsl.multipledex.ProxyApplication , 需要将其替换为实际开发的 Application ;
① ContextImpl 的 private Context mOuterContext 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
② ActivityThread 中的 ArrayList<Application> mAllApplications 集合中添加了 kim.hsl.multipledex.ProxyApplication 对象 ;
③ LoadedApk 中的 mApplication 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
④ ActivityThread 中的 Application mInitialApplication 成员是 kim.hsl.multipledex.ProxyApplication 对象 ;
替换 Application 就是需要替换上述对象的对应 Application 成员 ;