问题
上一篇文章:你想成为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合适。
对于系统源码这部分,我会随着经验的积累给这些方法里面添加一些核心的内容,但是这部分不影响我们今天的讲解,所以也可以不看这部分,直接看结论就好。
图片来自于(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