hook Activity

  • content
    {:toc}

    0x01

为了进一步弄懂,android中四大主键中的activity的启动过程,所以就进行了hook activity 进行处理。

hook的原理

就是通过动态代理或者静态代理的方式进行 偷梁换柱 的 方式进行,然后当程序执行到这个地方的时候,就会执行到我们自己所代理的 类或者方法上面,从而可以控制了这段代码的执行。

Hook选择点: 静态变量,单例。因为一旦创建了对象,它们就不容易变化,非常容易定位。

hook的使用过程:

  1. 找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);
//先把没注册的activity保存起来
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// intent.putExtra(HookAms.SAVE_AMS_INTENT, new Intent(this, NoRegisterActivity.class));
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
/**
* 通过分析,可以hook IActivityManager 的startActivity方法
* 然后进行hook
*/
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 : 用当前线程的classloader
*
*/

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Class[] interfaces = iActivityManagerObject.getClass().getInterfaces();
ProxyInvokehanlder proxyInvokehanlder = new ProxyInvokehanlder(iActivityManagerObject);

//IActivityManger的代理对象
Object proxyInstance = Proxy.newProxyInstance(contextClassLoader, interfaces, proxyInvokehanlder);

//偷梁换柱,把代理对象给ActivityManagerSingleton的mInstance,变成自己的代理类对象
mInstanceField.set(iActivityManagerSingleton, proxyInstance);


} catch (Exception e) {
e.printStackTrace();
}
}

这个过程中:

  1. 获取IActivityManager的对象,然后通过动态代理进行偷梁换柱。
  2. 最后把代理类设置在了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()));
//把curIntent保存起来
intent.putExtra(SAVE_AMS_INTENT, curIntent);
//把这个进行 欺骗处理 欺骗AMS 启动的是Fake的activity
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
/**
* 经过上面步骤,肯定还是不行的,打开的fakeActivity,我们要在
* 适当的时候,替换回来,才算可以
* <p>
* hookActivityThread$mH -> 中的$ 我是为了避免,AS编译器给个下划线加的,没有别的意思
*/
public static void hookActivityThread$mH() {
try {
//获取ActivityThread的字节码
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Field mHField = activityThreadClass.getDeclaredField("mH");
mHField.setAccessible(true);
//获取ActivityThread的对象
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
Object activityThreadObject = currentActivityThreadMethod.invoke(null);

Handler mHObject = (Handler) mHField.get(activityThreadObject);

//获取handler的mCallback对象
Class<?> handlerClass = Class.forName("android.os.Handler");
Field mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField.setAccessible(true);

//代理handle中的Callback
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) {
//这个类型,经过打印是LaunchActivityItem 类型的
Object launchActivityItemObject = mActivityCallbacksObject.get(0);
Log.e(TAG, "mActivityCallbacksObject: " + launchActivityItemObject);

Field mIntentField = launchActivityItemObject.getClass().getDeclaredField("mIntent");
mIntentField.setAccessible(true);

//拿到我们欺骗ams的intent,然后把我们真正需要的intent替换一下
Intent fakeIntent = (Intent) mIntentField.get(launchActivityItemObject);
Log.e(TAG, "intent: " + fakeIntent);

Intent intent = fakeIntent.getParcelableExtra(SAVE_AMS_INTENT);

//替换成想要的intent
mIntentField.set(launchActivityItemObject, intent);
}

} catch (Exception e) {
e.printStackTrace();
}

break;
default:
break;
}
mHandler.handleMessage(msg);
return false;
}
}

通过上面的,最后完成了未注册的Activity的启动

总结

  1. 知道了hook的简单使用,然后并进行了实践。

  2. 了解了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);
    //执行了EXECUTE_TRANSACTION,就是 159 那个what
    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:
    //最后都调用了ActivityThread中的对应方法
    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
    null /* customIntent */);
    break;
    case ON_START:
    mTransactionHandler.handleStartActivity(r, mPendingActions);
    break;
    case ON_RESUME:
    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
    r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
    break;
    //....

    ActivityThread # handleLaunchActivity -> ActivityThread # performLaunchActivity ->

    就找了熟悉的代码

    1
    2
    >activity = mInstrumentation.newActivity(
    cl, component.getClassName(), r.intent);