菜鸟带你Hook技术实战
Posted 风雨田
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了菜鸟带你Hook技术实战相关的知识,希望对你有一定的参考价值。
问题
上一篇文章:你想成为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 container, TaskRecord inTask)
...
if (err == ActivityManager.START_SUCCESS && aInfo == null)
//从Intent中无法找到相应的ActivityInfo
err = ActivityManager.START_INTENT_NOT_RESOLVED;
...
//[见2.5]
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
...
return err;
2.5
ActivityStackSupervisor.startActivityUncheckedLocked()
// sourceRecord是指调用者, r是指本次将要启动的Activity
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask)
...
//创建activity [见2.6]
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
...
2.6
ActivityStack.startActivityLocked()
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options)
if (doResume)
//[见2.7]
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
2.7
ActivityStackSupervisor.resumeTopActivitiesLocked()
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions)
...
if (isFrontStack(targetStack))
//[见流程2.8]
result = targetStack.resumeTopActivityLocked(target, targetOptions);
...
2.8
AS.resumeTopActivityLocked
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options)
...
//[见2.9]
result = resumeTopActivityInnerLocked(prev, options);
return result;
2.9
AS.resumeTopActivityInnerLocked()
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options)
...
//[2.10]
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
2.10
ASS.startSpecificActivityLocked()
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig)
ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
//真正的启动Activity【见流程2.11】
realStartActivityLocked(r, app, andResume, checkConfig);
//当进程不存在则创建进程 [见2.12]
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
2.11
ASS.realStartActivityLocked()
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException
//[见2.12]
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
2.12
ApplicationThreadProxy.scheduleLaunchActivity()
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException
//[见3.1]
mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);
3.1
ApplicationThreadNative.onTransact()
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
//[见3.1]
scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
referrer, voiceInteractor, procState, state, persistentState, ri, pi,
notResumed, isForward, profilerInfo);
3.1
ApplicationThread.scheduleLaunchActivity()
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo)
//[见3.2]
sendMessage(H.LAUNCH_ACTIVITY, r);
3.2
ActivityThread.java::H.handleMessage
public void handleMessage(Message msg)
switch (msg.what)
case LAUNCH_ACTIVITY:
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//[见3.3]
handleLaunchActivity(r, null);
break;
...
3.3
ActivityThread.handleLaunchActivity()
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent)
...
//最终回调目标Activity的onCreate
//见[3.4]
Activity a = performLaunchActivity(r, customIntent);
if (a != null)
//最终回调目标Activity的onStart,onResume.
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed)
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
r.paused = true;
else
//存在error则停止该Activity
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
3.4
ActivityThread.performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)
Activity activity = null;
try
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//见[3.5]
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
catch (Exception e)
...
3.5
Instrumentation.newActivity()
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException
return (Activity)cl.loadClass(className).newInstance();
我们最后看到在ActivityThread.performLaunchActivity()
方法中创建了Activity,在这个过程中我分别用1.2.3标记不同的进程,1.3分别是app进程,2是system_server进程。
- 1标记的进程也就是app进程,主要将要启动的Activity信息(Activity名称,当前所在包名),当前应用的ApplicationThread对象,intent(传递进去的参数)等。
- 2标记的进程也就是system_server进程,进行各种判断检查,信息保存,组件调度等等
- 3标记的进程还是app进程,此时主要是创建Activity对象,回调各种回调方法,根据2标记的进程来的信息。
其中ActivityManagerNative.getDefault()
得到的是AMS的代理,与AMS进行通信。代码如下:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>()
protected IActivityManager create()
//获取名为"activity"的服务,服务都注册到ServiceManager来统一管理
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
;
public abstract class Singleton<T>
public final T get()
synchronized (this)
if (mInstance == null)
//首次调用create()来获取AMP对象
mInstance = create();
return mInstance;
ActivityManagerNative.getDefault()
static public IActivityManager getDefault()
return gDefault.get();
gDefault为Singleton类型对象,此次采用单例模式,mInstance为IActivityManager类的代理对象,即ActivityManagerProxy。
那什么从AMS给APP通信呢?
Activity.startActivity()
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options)
if (mParent == null)
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), ...);...
else
...
我们看到调用startActivityForResult()
这个方法的时候使用mMainThread.getApplicationThread()
作为参数,这个参数得到的是什么?
public class Activity extends ...
ActivityThread mMainThread;
ActivityThread.java
public final class ActivityThread
final ApplicationThread mAppThread = new ApplicationThread();
final H mH = new H();
public ApplicationThread getApplicationThread()
return mAppThread;
/*内部类*/
private class ApplicationThread extends IApplicationThread.Stub
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async)
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async)
msg.setAsynchronous(true);
mH.sendMessage(msg);
...
/*内部类*/
private class H extends Handler
public void handleMessage(Message msg)
...
从结构上看出来,是将ActivityThread的内部类ApplicationThread的对象传入AMS中。这个对象处理IApplicationThread接口所有方法都是利用ActivityThread类的成员变量H进行发送消息。也就是AMS通过ApplicationThread对象控制APP进程这端。所以app进程这边的实现逻辑全部在H类中
寻找hook点
我们并没有办法通过hook改变别的进程信息,比如AMS。而且通过源码我们知道最后创建Activity对象也是回归到App进程,所以我们就可以在app进程真正创建Activity对象的时候偷梁换柱。
比如我们有个废掉的Activity叫做StubActivity,这个Activity是在我们清单文件中声明了的,我们要启动TargetActivity。我们需要在Activity检查之前进行拦截,将我们的TargetActivity替换成StubActivity,这样系统就认为我们要启动StubActivity。而我们在hook的时候将TargetActivity信息保存下来,当系统确定要创建Activity的时候,我们在将信息还原。这个时候就创建的是TargetActivity。
所以我们hook点如下:
- 对ActivityManagerNative的
Singleton gDefault
对象中的mInstance进行hook,他是IActivityManager
与AMS交互的Binder代理。 - 我们队ActivityThread.mH对象进行hook,更换mCallback,使得在LAUNCH_ACTIVITY这种情况偷换为TargetActivity的Intent信息。
项目代码解析
一:需要在清单文件中声明
<application>
<!--随便声明一个替身Activity-->
<activity android:name=".StubActivity"/>
</application>
二:一个空的Activity
public class StubActivity extends Activity
// dummy
三:对两个hook点进行hook
public class AMSHookHelper
public static final String EXTRA_TARGET_INTENT = "extra_target_intent";
/**
* 主要完成的操作是 "把真正要启动的Activity临时替换为在AndroidManifest.xml中声明的替身Activity"
*/
public static void hookActivityManagerNative() throws Exception
Field gDefaultField =null;
if (Build.VERSION.SDK_INT >= 26)
Class<?> activityManager = Class.forName("android.app.ActivityManager");
gDefaultField = activityManager.getDeclaredField("IActivityManagerSingleton");
else
Class<?> activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
gDefaultField.setAccessible(true);
Object gDefault = gDefaultField.get(null);
// gDefault是一个 android.util.Singleton对象; 我们取出这个单例里面的字段
Class<?> singleton = Class.forName("android.util.Singleton");
Field mInstanceField = singleton.getDeclaredField("mInstance");
mInstanceField.setAccessible(true);
// ActivityManagerNative 的gDefault对象里面原始的 IActivityManager对象
Object rawIActivityManager = mInstanceField.get(gDefault);
// 创建一个这个对象的代理对象, 然后替换这个字段, 让我们的代理对象帮忙干活
Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[] iActivityManagerInterface , new IActivityManagerHandler(rawIActivityManager));
mInstanceField.set(gDefault, proxy);
public static void hookActivityThreadHandler() throws Exception
// 先获取到当前的ActivityThread对象
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Field currentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
currentActivityThreadField.setAccessible(true);
Object currentActivityThread = currentActivityThreadField.get(null);
// 由于ActivityThread一个进程只有一个,我们获取这个对象的mH
Field mHField = activityThreadClass.getDeclaredField("mH");
mHField.setAccessible(true);
Handler mH = (Handler) mHField.get(currentActivityThread);
Field mCallBackField = Handler.class.getDeclaredField("mCallback");
mCallBackField.setAccessible(true);
mCallBackField.set(mH, new ActivityThreadHandlerCallback(mH));
四:拦截方法实现
class IActivityManagerHandler implements InvocationHandler
private static final String TAG = "IActivityManagerHandler";
Object mBase;
public IActivityManagerHandler(Object base)
mBase = base;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
if ("startActivity".equals(method.getName()))
Intent raw;
int index = 0;
for (int i = 0; i < args.length; i++)
if (args[i] instanceof Intent)
index = i;
break;
raw = (Intent) args[index];
Intent newIntent = new Intent();
String stubPackage = "com.hookactivity.cn";
ComponentName componentName = new ComponentName(stubPackage, StubActivity.class.getName());
newIntent.setComponent(componentName);
newIntent.putExtra(AMSHookHelper.EXTRA_TARGET_INTENT, raw);
args[index] = newIntent;
Log.d(TAG, "hook success");
return method.invoke(mBase, args);
return method.invoke(mBase, args);
class ActivityThreadHandlerCallback implements Handler.Callback
Handler mBase;
public ActivityThreadHandlerCallback(Handler base)
mBase = base;
@Override
public boolean handleMessage(Message msg)
switch (msg.what)
// ActivityThread里面 "LAUNCH_ACTIVITY" 这个字段的值是100
case 100:
handleLaunchActivity(msg);
break;
mBase.handleMessage(msg);
return true;
private void handleLaunchActivity(Message msg)
Object obj = msg.obj;
try
// 把替身恢复成真身
Field intent = obj.getClass().getDeclaredField("intent");
intent.setAccessible(true);
Intent raw = (Intent) intent.get(obj);
Intent target = raw.getParcelableExtra(AMSHookHelper.EXTRA_TARGET_INTENT);
raw.setComponent(target.getComponent());
catch (NoSuchFieldException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
五:主入口
public class MainActivity extends Activity
@Override
protected void attachBaseContext(Context newBase)
super.attachBaseContext(newBase);
try
AMSHookHelper.hookActivityManagerNative();
AMSHookHelper.hookActivityThreadHandler();
catch (Throwable throwable)
throw new RuntimeException("hook failed", throwable);
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setText("启动TargetActivity");
button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
// TargetActivity并没有在AndroidManifest.xml中声明
startActivity(new Intent(MainActivity.this, TargetActivity.class));
);
setContentView(button);
六:目标Activity
不能再清单中注册
public class TargetActivity extends Activity
private static final String TAG = "TargetActivity";
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("TargetActivity 启动成功!!!");
setContentView(tv);
以上是对系统启动activity的Hook,基本能满足我们的一些特殊的需求
下面我们再讲讲当我们需要hook任意服务的时候应该怎么做呢?
获取服务&注册
ServiceManager.getService()
public static IBinder getService(String name)
try
IBinder service = sCache.get(name); //先从缓存中查看
if (service != null)
return service;
else
return getIServiceManager().getService(name);//[1.2]
catch (RemoteException e)
Log.e(TAG, "error in getService", e);
return null;
1.2 ServiceManagerNative.java ::ServiceManagerProxy()
这里可以看到底层的ServiceManager进行交互,通过底层的ServiceManager返回对应服务的IBinder对象
class ServiceManagerProxy implements IServiceManager
public IBinder getService(String name) throws RemoteException
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
//mRemote为BinderProxy
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//从reply里面解析出获取的IBinder对象
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
关于底层ServiceManager
//有关代码目录
framework/native/cmds/servicemanager/
- service_manager.c
- binder.c
kernel/drivers/ (不同Linux分支路径略有不同)
- staging/android/binder.c
- android/binder.c
关于ServiceManager的启动过程如下:
1. 打开binder驱动:binder_open;
2. 注册成为binder服务的大管家:binder_become_context_manager;
3. 进入无限循环,处理client端发来的请求:binder_loop;
ServiceManager
是由init
进程通过解析init.rc
文件而创建的,其所对应的可执行程序/system/bin/servicemanager
,所对应的源文件是service_manager.c
,进程名为/system/bin/servicemanager
。
可见ServiceManager相当于一个房屋中介,有人过来租房子,有人过来出租。那么系统服务在什么时候进行注册呢?
系统服务的注册
这一部分在SystemServer
中,我们只是举一个例子的代码
//ActivityManagerService.java->setSystemProcess()
public void setSystemProcess()
try
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE)
ServiceManager.addService("cpuinfo", new CpuBinder(this));
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
...
catch (PackageManager.NameNotFoundException e)
...
可见在SystemServer中都是通过ServiceManager.addService()方法将服务添加到大管家中。
SystemServer的启动时机是在Zygote进程启动时候通过抛出异常的办法执行SystemServer.main()方法进入java世界。
启动的一些系统服务如下:
EntropyService:熵(shang)服务,用于产生随机数
PowerManagerService:电源管理服务
ActivityManage搜索rService:最核心服务之一,Activity管理服务
TelephonyRegistry:电话服务,电话底层通知服务
PackageManagerService:程序包管理服务
AccountManagerService:联系人帐户管理服务
ContentService:内容提供器的服务,提供跨进程数据交换
LightsService:光感应传感器服务
BatteryService:电池服务,当电量不足时发广播
VibratorService:震动器服务
AlarmManagerService:闹钟服务
WindowManagerService:窗口管理服务
BluetoothService:蓝牙服务
InputMethodManagerService:输入法服务,打开关闭输入法
AccessibilityManagerService:辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击、焦点等事件分发管理服务
DevicePolicyManagerService:提供一些系统级别的设置及属性
StatusBarManagerService:状态栏管理服务
ClipboardService:粘贴板服务
NetworkManagementService:手机网络管理服务
TextServicesManagerService:
NetworkStatsService:手机网络状态服务
NetworkPolicyManagerService:
WifiP2pService:Wifi点对点直联服务
WifiService:WIFI服务
ConnectivityService:网络连接状态服务
ThrottleService:modem节流阀控制服务
MountService:磁盘加载服务,通常也mountd和vold服务结合
NotificationManagerService:通知管理服务,通常和StatusBarManagerService
DeviceStorageMonitorService:存储设备容量监听服务
LocationManagerService:位置管理服务
CountryDetectorService:检查当前用户所在的国家
SearchManagerService:搜索管理服务
DropBoxManagerService:系统日志文件管理服务(大部分程序错误信息)
WallpaperManagerService:壁纸管理服务
Audioservice:AudioFlinger上层的封装的音量控制管理服务
UsbService:USB Host和device管理服务
UiModeManagerService:UI模式管理服务,监听车载、座机等场合下UI的变化
BackupManagerService:备份服务
AppWidgetService:应用桌面部件服务
RecognitionManagerService:身份识别服务
DiskStatsService:磁盘统计服务
SamplingProfilerService:性能统计服务
NetworkTimeUpdateService:网络时间更新服务
研究系统服务的Hook点
我们在应用中获取系统服务使用如下代码获取AMS的代理服务:
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
public Object getSystemService(String name)
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
可以看到从一个Map结构中根据名字得到service,那么一个服务在java层怎么注册的呢?
registerService(ACCOUNT_SERVICE, new ServiceFetcher()
public Object createService(ContextImpl ctx)
IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
IAccountManager service = IAccountManager.Stub.asInterface(b);
return new AccountManager(ctx, service);
);
registerService(ACTIVITY_SERVICE, new ServiceFetcher()
public Object createService(ContextImpl ctx)
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
);
可以看出,核心不变,只是简单包装成了一个ServiceFetcher对象而已。
但是我们对于ActivityManager的使用,查看startActivity/startService就会知道我们并没有像上面一样获取AM服务,而是通过ActivityManagerNative.getDefault()
完成
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>()
protected IActivityManager create()
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);//进行如下调用
return am;
;
static public IActivityManager asInterface(IBinder obj)
if (obj == null)
return null;
IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null)
return in;
return new ActivityManagerProxy(obj);
queryLocalInterface()方法的目的是如果是
以上是关于菜鸟带你Hook技术实战的主要内容,如果未能解决你的问题,请参考以下文章
『Python开发实战菜鸟教程』实战篇:一文带你了解人脸识别应用原理及手把手教学实现自己的人脸识别项目
『Python开发实战菜鸟教程』实战篇:一文带你了解人脸识别应用原理及手把手教学实现自己的人脸识别项目
『Python开发实战菜鸟教程』实战篇:一文带你了解人脸识别应用原理及手把手教学实现自己的人脸识别项目
『Python开发实战菜鸟教程』实战篇:一文带你了解人脸识别应用原理及手把手教学实现自己的人脸识别项目