为了进一步弄懂,android中四大主键中的activity的启动过程,所以就进行了hook activity 进行处理。
hook的原理
就是通过动态代理或者静态代理的方式进行 偷梁换柱 的 方式进行,然后当程序执行到这个地方的时候,就会执行到我们自己所代理的 类或者方法上面,从而可以控制了这段代码的执行。
Hook选择点: 静态变量,单例。因为一旦创建了对象,它们就不容易变化,非常容易定位。
hook的使用过程:
找hook点。静态或者单例对象,尽量hook public的方法。
2. 选择合适的代理方式,如果是接口,就用动态代理。
3. 偷梁换柱—> 用自己实现的代理对象替换原始对象。
注意: 由于android 版本非常的多,通过反射的过程中,可以有很多的api不太一样,这样就会造成,要进行兼容处理。
0x02 hook IActivityManager,然后进行不注册Activity,然后也进行启动
原理
就是通过一个正常的 activity 通过 startActivity启动,启动的时候,然后用intent先保存好没有注册的activity的intent,然后进行传递到AMS中,AMS通过 PKMS存好的 原来App安装的Mainfest的文件,里面的Activity, Service,ContentProvider, BroadcastReceiver 的注册好的,然后找到对应的Activity。最后从AMS回来。
目的
一、开始写代码
1 2 3 4 5 6 7 8 9
| public void hookAMS(View view) { HookAms.hookIActivityManager(); HookAms.hookActivityThread$mH(); Intent intent = new Intent(this, NoRegisterActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
|
通过startActivity我们知道,最后跑到了 AMS的startActivity中去了
hook点就是AMS的startActivity,实际上AMS是实现了IActivityManager的接口,所以直接动态代理去实现。
二、hook ActivityManager中的IActivityManagerSingleton成员变量
为什么要hook ActivityManager的IActivityManagerSingleton呢,看下图:

因为在Instrumention 中启动activity是通过AMS的startActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
public static void hookIActivityManager() { try {
Class<?> activityManagerClass = Class.forName("android.app.ActivityManager"); Field iActivityManagerSingletonField = activityManagerClass.getDeclaredField("IActivityManagerSingleton"); iActivityManagerSingletonField.setAccessible(true); Object iActivityManagerSingleton = iActivityManagerSingletonField.get(null);
Class<?> singletonClass = Class.forName("android.util.Singleton"); Field mInstanceField = singletonClass.getDeclaredField("mInstance"); mInstanceField.setAccessible(true);
Object iActivityManagerObject = mInstanceField.get(iActivityManagerSingleton);
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Class[] interfaces = iActivityManagerObject.getClass().getInterfaces(); ProxyInvokehanlder proxyInvokehanlder = new ProxyInvokehanlder(iActivityManagerObject);
Object proxyInstance = Proxy.newProxyInstance(contextClassLoader, interfaces, proxyInvokehanlder);
mInstanceField.set(iActivityManagerSingleton, proxyInstance);
} catch (Exception e) { e.printStackTrace(); } }
|
这个过程中:
- 获取IActivityManager的对象,然后通过动态代理进行偷梁换柱。
- 最后把代理类设置在了ActivityManger里面去
三、ProxyInvokehanlder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| static class ProxyInvokehanlder implements InvocationHandler { private static final String TAG = "ProxyInvokehanlder"; private Object mBase;
public ProxyInvokehanlder(Object base) { mBase = base; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.e(TAG, "invoke: " + method.getName());
if ("startActivity".equals(method.getName())) { int curIntentIndex = -1; Intent curIntent = null; for (int i = 0; i < args.length; i++) { if (args[i] instanceof Intent) { curIntentIndex = i; curIntent = (Intent) args[i]; } Log.e(TAG, "arg: " + args[i]); }
if (curIntent != null) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.zhousaito.hookactivity", FakeActivity.class.getName())); intent.putExtra(SAVE_AMS_INTENT, curIntent); args[curIntentIndex] = intent; } }
return method.invoke(mBase, args); } }
|
主要工作就是把自己未注册的Activity的intent,换成注册好的 Activity,然后欺骗AMS
四、通过以上方式,可以启动Activity,但是FakeActivity是欺骗AMS的Activity
五、通过hook activityThread里面的mH这个类进行替换回来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
public static void hookActivityThread$mH() { try { Class<?> activityThreadClass = Class.forName("android.app.ActivityThread"); Field mHField = activityThreadClass.getDeclaredField("mH"); mHField.setAccessible(true); Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread"); Object activityThreadObject = currentActivityThreadMethod.invoke(null);
Handler mHObject = (Handler) mHField.get(activityThreadObject);
Class<?> handlerClass = Class.forName("android.os.Handler"); Field mCallbackField = handlerClass.getDeclaredField("mCallback"); mCallbackField.setAccessible(true);
mCallbackField.set(mHObject, new ProxyCallback(mHObject));
} catch (Exception e) { e.printStackTrace(); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| static class ProxyCallback implements Handler.Callback { private static final String TAG = "ProxyCallback"; Handler mHandler;
public ProxyCallback(Handler handler) { mHandler = handler; }
@Override public boolean handleMessage(Message msg) { Log.e(TAG, "what: " + msg.what + ", obj: " + msg.obj); switch (msg.what) { case 159: try { Class<?> clientTransactionClass = Class.forName("android.app.servertransaction.ClientTransaction"); Field mActivityCallbacks = clientTransactionClass.getDeclaredField("mActivityCallbacks"); mActivityCallbacks.setAccessible(true); List mActivityCallbacksObject = (List) mActivityCallbacks.get(msg.obj); if (mActivityCallbacksObject.size() > 0) { Object launchActivityItemObject = mActivityCallbacksObject.get(0); Log.e(TAG, "mActivityCallbacksObject: " + launchActivityItemObject);
Field mIntentField = launchActivityItemObject.getClass().getDeclaredField("mIntent"); mIntentField.setAccessible(true);
Intent fakeIntent = (Intent) mIntentField.get(launchActivityItemObject); Log.e(TAG, "intent: " + fakeIntent);
Intent intent = fakeIntent.getParcelableExtra(SAVE_AMS_INTENT);
mIntentField.set(launchActivityItemObject, intent); }
} catch (Exception e) { e.printStackTrace(); }
break; default: break; } mHandler.handleMessage(msg); return false; } }
|
通过上面的,最后完成了未注册的Activity的启动
总结
知道了hook的简单使用,然后并进行了实践。
了解了Activity的启动过程:
Activity # startActivityForResult -> Instrumentation# execStartActivity -> ActivityManager.getService()#startActivity (实际上到了 AMS # startActivity) ->AMS#startActivityAsUser -> ActivityStartController 的handle发送消息 doPendingActivityLaunches -> ActivityStarter # startResolvedActivity -> ActivityStarter#startActivity(构造方法参数贼多的那个) ->ActivityStack.sendActivityResultLocked -> mService.getLifecycleManager().scheduleTransaction就是AMS中的LifecycleManager的scheduleTransaction -> ClientTransaction # schedule -> IApplicationThread#scheduleTransaction 就相当于ApplicationThread的中的scheduleTransaction方法 -> ActivityThread的继承类 scheduleTransaction 方法
1 2 3 4 5
| >void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); >}
|
-> TransactionExecutor # execute -> TransactionExecutor # cycleToPath -> TransactionExecutor #performLifecycleSequence
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| >private void performLifecycleSequence(ActivityClientRecord r, IntArray path) { final int size = path.size(); for (int i = 0, state; i < size; i++) { state = path.get(i); log("Transitioning to state: " + state); switch (state) { case ON_CREATE: mTransactionHandler.handleLaunchActivity(r, mPendingActions, null ); break; case ON_START: mTransactionHandler.handleStartActivity(r, mPendingActions); break; case ON_RESUME: mTransactionHandler.handleResumeActivity(r.token, false , r.isForward, "LIFECYCLER_RESUME_ACTIVITY"); break;
|
ActivityThread # handleLaunchActivity -> ActivityThread # performLaunchActivity ->
就找了熟悉的代码
1 2
| >activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);
|