菜鸟带你Hook技术实战

本文介绍了Android中Hook技术的应用,通过分析系统启动Activity的流程,找到Hook点,实现在不修改AndroidManifest.xml的情况下启动未注册的Activity。此外,还探讨了如何Hook系统服务,以剪贴板服务为例,展示了如何替换系统服务并控制其行为。通过理解Binder机制和动态代理,可以实现对任意系统服务的Hook,为插件化和动态加载等功能提供可能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

上一篇文章:你想成为Android高级工程师你还得学习Hook中我们提了一个问题:
我们如果要启动一个activity,我们的做法是1. 在AndroidManifest.xml中声明一个Activity 2. startActivity,如果不在AndroidManifest.xml中声明,启动activity会报错(android.content.ActivityNotFoundException)。但是我们想,我们使用插件化,按照正常的思维是不是要将插件化中的所有activity都要声明到清单文件中才可以。所以我们要怎么做才能hook系统启动activity。通过hook我们对AndroidManifest.xml文件中的activity进行偷梁换柱,换成我们没有注册在清单文件中的activity?
下次文章我们为大家详细分析

其实答案就是hook系统启动activity

系统源码流程

通过对系统源码的了解,我们才能知道从哪里hook合适。

对于系统源码这部分,我会随着经验的积累给这些方法里面添加一些核心的内容,但是这部分不影响我们今天的讲解,所以也可以不看这部分,直接看结论就好。

image

图片来自于(gityuan)

系统源码目录

frameworks/base/services/core/java/com/android/server/am/
  - ActivityManagerService.java
  - ActivityStackSupervisor.java
  - ActivityStack.java
  - ActivityRecord.java
  - ProcessRecord.java

frameworks/base/core/java/android/app/
  - IActivityManager.java
  - ActivityManagerNative.java (内含AMP)
  - ActivityManager.java

  - IApplicationThread.java
  - ApplicationThreadNative.java (内含ATP)
  - ActivityThread.java (内含ApplicationThread)

  - ContextImpl.java

1.1 Activity.startActivity

public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);//[见1.2]
    }
}

1.2 Activity.startActivityForResult

public void startActivityForResult(Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        //[见1.3]
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        //此时requestCode =-1
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
    } else {
        ...
    }
}

1.3 Instrumentation.execStartActivity()

  • caller: 当前应用的ApplicationThread对象mAppThread;
  • callingPackage: 调用当前ContextImpl.getBasePackageName(),获取当前Activity所在包名;
  • intent: 这便是启动Activity时,传递过来的参数;
  • resolvedType: 调用intent.resolveTypeIfNeeded而获取;
  • resultTo: 来自于当前Activity.mToken
  • resultWho: 来自于当前Activity.mEmbeddedID
  • requestCode = -1;
  • startFlags = 0;
  • profilerInfo = null;
  • options = null;
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {

    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        ...
        //[见1.4]
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //检查activity是否启动成功[1.3.1]
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

1.3.1 Instrumentation.checkStartActivityResult()

public class Instrumentation {
   
   
    /** @hide */
    public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException("No Activity found to handle " + intent);
            ...
        }
}

1.4 ActivityManagerProxy.startActivity()

class ActivityManagerProxy implements IActivityManager {
    ...
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        //通过Binder传递数据
        ...
        //[见2.1]
        intent.writeToParcel(data, 0);//将Intent写入Binder
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        ...
        return result;
    }
    ...
}

==AMP经过binder IPC,进入ActivityManagerNative(简称AMN)。接下来程序进入了system_servr进程,开始继续执行==

2.1 ActivityManagerNative.onTransact()

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {  
      ...
      Intent intent = Intent.CREATOR.createFromParcel(data);
      ...
      //[见2.2]
      int result = startActivity(app, callingPackage, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
      ...
      return true;
    }
    ...
    }    
}

2.2 ActivityManagerService.startActivity

public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
        resultWho, requestCode, startFlags, profilerInfo, options,
        UserHandle.getCallingUserId());
}

public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    //[2.3]
    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, options, false, userId, null, null);
}

2.3 ActivityStackSupervisor.startActivityMayWait()

  • caller = ApplicationThreadProxy, 用于跟调用者进程ApplicationThread进行通信的binder代理类.
  • callingUid = -1;
  • callingPackage = ContextImpl.getBasePackageName(),获取调用者Activity所在包名
  • intent: 这是启动Activity时传递过来的参数;
  • resolvedType = intent.resolveTypeIfNeeded
  • voiceSession = null;
  • voiceInteractor = null;
  • resultTo = Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息
  • resultWho = Activity.mEmbeddedID, 其中Activity是指调用者所在Activity
  • requestCode = -1;
  • startFlags = 0;
  • profilerInfo = null;
  • outResult = null;
  • config = null;
  • options = null;
  • ignoreTargetSecurity = false;
  • userId = AMS.handleIncomingUser, 当调用者userId跟当前处于同一个userId,则直接返回该userId;当不相等时则根据调用者userId来决定是否需要将callingUserId转换为mCurrentUserId.
  • iContainer = null;
  • inTask = null;
final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) {
    ...
    boolean componentSpecified = intent.getComponent() != null;
    //创建新的Intent对象,即便intent被修改也不受影响
    intent = new Intent(intent);
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
    synchronized (mService) {
        //[见2.4]
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);
    }
    ...
    return res;
}

2.4 ActivityStackSupervisor.startActivityLocked()

这里要注意的是如果err = ActivityManager.START_INTENT_NOT_RESOLVED;就会有1.3.1所述代码的异常。

final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, ActivityInfo aInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, Bundle options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer con
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值