先上startActivity的流程图和ActivityThread启动activity的流程图,写的代码对照这个流程图就清晰很多了
startActivity流程图.png
ActivityThread启动activity流程图.png
为了让AMS验证通过,需要在AndroidManifest中注册的Activity(StubActivity)占坑,在启动插件Activity(TargetActivity)时替换为占坑Activity(StubActivity),达到一个欺上瞒下的作用,当AMS验证通过之后,需要将启动的占坑Activity(StubActivity)替换为插件Activity(TargetActivity)。
总的来说有两个步骤
1.将请求启动的插件TargetActivity替换为占坑StubActivity欺骗AMS通过验证
2.骗过AMS验证后,将占坑StubActivity替换回插件TargetActivity
//启动一个TargetActivity
//但是在AMS验证的时候,是StubActivity给AMS验证
Intent intent = new Intent(this,TargetActivity.class);
startActivity(intent);
下面是分析AMS的源码:
hook的点是IActivityManager和Handler
先讲hook IActivityManager,先看IActivityManager源码
public interface IActivityManager extends IInterface {
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, String profileFile,
ParcelFileDescriptor profileFd, Bundle options) throws RemoteException;
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, String profileFile,
ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, String profileFile,
ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
public int startActivityWithConfig(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int startFlags, Configuration newConfig,
Bundle options, int userId) throws RemoteException;
IActivityManager是实现了IInterface接口,可知是通过Binder通讯的,所以我们可以通过动态代理Proxy修改其中的Intent来达到欺骗AMS。
现在再看看在那里可以获取到IActivityManager的实例(注意:Android O开始重构了AMS代码,所以需要版本兼容)。O以上的版本可以在ActivityManager中获得IActivityManager实例,O以下的版本可以在ActivityManagerNative中获取。
Android O以上获取IActivityManager:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
ANdroid O以下获取IActivityManager:
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
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);
}
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
所以我们获取IActivityManager的时候就要判断版本了,再看看两个都用到了Singleton这个类。
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
实现获取IActivityManager并代理的代码
public static void hookActivityManager(final Activity activity){
try{
Field gDefaultField;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.O){
//获取的Singleton<IActivityManager>成员
Class<?> amClaz = Class.forName("android.app.ActivityManager");
gDefaultField = amClaz.getDeclaredField("IActivityManagerSingleton");
}else {
//获取的Singleton<IActivityManager>成员
Class<?> amClaz = Class.forName("android.app.ActivityManagerNative");
gDefaultField = amClaz.getDeclaredField("gDefault");
}
gDefaultField.setAccessible(true);
//获取Singleton<IActivityManager> gDefault的真实对象
Object gDefault = gDefaultField.get(null);
Class singletonClaz = Class.forName("android.util.Singleton");
Field mInstance = singletonClaz.getDeclaredField("mInstance");
mInstance.setAccessible(true);
//获取到了IActivityManager的真实对象 相当于getService或者getDefault
//gDefault关联Singleton,所以mInstance就是IActivityManager的实例
final Object iam = mInstance.get(gDefault);
//获取当前线程的ClassLoader
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//动态代理的接口
Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
//动态代理IActivityManager的接口
Object proxy = Proxy.newProxyInstance(classLoader, new Class[]{iActivityManagerInterface},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断调用的方法,如果是startActivity的话,拦截,修改里面的Intent
if (method.getName().equals("startActivity")){
int index = 0;
Intent rawIntent = null;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Intent){
index = i;
rawIntent = (Intent) args[i];
break;
}
}
//把在清单文件中注册的StubActivity给换上去 欺骗AMS
Intent newIntent = new Intent();
newIntent.setComponent(new ComponentName
(activity.getPackageName(),StubActivity.class.getName()));
newIntent.putExtra(TARGET_INTENT,rawIntent);
args[index] = newIntent;
}
//调用方法 相当于iam.startActivity(args)
return method.invoke(iam,args);
}
});
//把修改的后的设置回去
mInstance.set(gDefault,proxy);
}catch (Exception e){
Log.e(TAG, "hookActivityManager: exception" + e.getMessage() );
e.printStackTrace();
}
}
接下来,我们要把这个rawIntent给改回去,所以需要hook Handler,可以从ActivityThread入手,ActivityThread由于也被重构了,所以Android O的上下版本略有不同
先看源码找思路:
首先一个app 只有一个ActivityThread 然后就只有一个mH,我们app所有的activity的生命周期的处理都在mH的handleMessage里面处理的。在Android 8.0之前,不同的生命周期对应不同的msg.what处理,在Android 8.0 改成了全部由EXECUTE_TRANSACTION来处理
public final class ActivityThread extends ClientTransactionHandler {
static volatile IPackageManager sPackageManager;
final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
final H mH = new H();
//ActivityThread 一个app进程 只有一个sCurrentActivityThread
private static volatile ActivityThread sCurrentActivityThread;
}
Android O以上在ActivityThread的内部类H中
class H extends Handler {
//public static final int LAUNCH_ACTIVITY = 100;
//public static final int PAUSE_ACTIVITY = 101;
//public static final int PAUSE_ACTIVITY_FINISHING= 102;
//public static final int STOP_ACTIVITY_SHOW = 103;
//public static final int STOP_ACTIVITY_HIDE = 104;
//public static final int SHOW_WINDOW = 105;
//public static final int HIDE_WINDOW = 106;
//public static final int RESUME_ACTIVITY = 107;
//public static final int SEND_RESULT = 108;
//public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
~~~
public static final int EXECUTE_TRANSACTION = 159;
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
}
}
}
Android O以下在ActivityThread的内部类H中
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
~~~
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
}
}
}
}
在Android O及以上所有的生命周期都走的是EXECUTE_TRANSACTION,在Android O以下不同的生命周期对应不同的msg.what处理
下一步,从H也就是Handler入手
//Handler 源码
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
由于ActivityThread中的H用的是空构造方法new H(),所以mCallback为空。再看dispatchMessage这个方法,会判断mCallback != null,我们可以通过给mCallback赋值,然后在里面做还原操作。
所以实现还原的操作如下代码:
public static void hookHandler(){
try {
//获取ActivityThread的class
Class<?> atClass = Class.forName("android.app.ActivityThread");
//获取ActivityThread里面的成员 sCurrentActivityThread
Field sCurrentActivityThreadField = atClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true);
//获取sCurrentActivityThread的实例
//sCurrentActivityThread是一个静态成员,所以get不需要传object,传null就可以了
Object sCurrentActivityThread = sCurrentActivityThreadField.get(null);
//获取成员mH H继承Handler
Field mHField = atClass.getDeclaredField("mH");
mHField.setAccessible(true);
//获取mH的实例并强转Handler
final Handler mH = (Handler) mHField.get(sCurrentActivityThread);
////获取Handler CallBack
Field mCallbackField = Handler.class.getDeclaredField("mCallback");
mCallbackField.setAccessible(true);
//dispatchMessage方法中会判断mCallback是否为空,不为空就调用Callback的handleMessage
//所以可以在mCallback里面做换回rawIntent的操作
//给mCallback赋值
mCallbackField.set(mH, new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
//launch_activity 两个版本低版本的是 LAUNCH_ACTIVITY = 100
//高版本的是 EXECUTE_TRANSACTION = 159
switch (msg.what){
case 100:{
try {
//msg.obj = ActivityClientRecord
//相当于反射获取ActivityClientRecord的 intent
Field intentField = msg.obj.getClass().getDeclaredField("intent");
intentField.setAccessible(true);
Intent intent = (Intent) intentField.get(msg.obj);
//把存放在intent里面的rawIntent取出来,替换回来
Intent rawIntent = intent.getParcelableExtra(TARGET_INTENT);
intent.setComponent(rawIntent.getComponent());
} catch (Exception e) {
Log.e(TAG, "handleMsg 100: Exception" + e.getMessage());
e.printStackTrace();
}
}
break;
//从AndroidP开始重构了状态模式
// 首先一个app 只有一个ActivityThread 然后就只有一个mH
//我们app所有的activity的生命周期的处理都在mH的handleMessage里面处理
//在Android 8.0之前,不同的生命周期对应不同的msg.what处理
//在Android 8.0 改成了全部由EXECUTE_TRANSACTION来处理
case 159:{
try{
//obj == ClientTransaction
Object obj = msg.obj;
//获取ClientTransaction下的mActivityCallbacks
//private List<ClientTransactionItem> mActivityCallbacks;
//ClientTransactionItem有个子类是LaunchActivityItem,我们需要的是这个子类
Field mActivityCallbacksField = obj.getClass().getDeclaredField("mActivityCallbacks");
mActivityCallbacksField.setAccessible(true);
//获取mActivityCallbacks的实例
List<Object> mActivityCallbacks = (List<Object>) mActivityCallbacksField.get(obj);
Log.e(TAG, "handleMessage: mActivityCallbacks= " + mActivityCallbacks);
if (mActivityCallbacks.size() > 0 ){
String luanchName = "android.app.servertransaction.LaunchActivityItem";
//LaunchActivityItem是ClientTransactionItem的子类
// 而Intent的信息则存在LaunchActivityItem的mIntent中
if (mActivityCallbacks.get(0).getClass().getCanonicalName().equals(luanchName)){
Object object = mActivityCallbacks.get(0);
Field intentField = object.getClass().getDeclaredField("mIntent");
intentField.setAccessible(true);
Intent intent = (Intent) intentField.get(object);
Intent rawIntent = intent.getParcelableExtra(TARGET_INTENT);
intent.setComponent(rawIntent.getComponent());
}
}
}catch (Exception e){
Log.e(TAG, "handleMsg 159: Exception" + e.getMessage());
e.printStackTrace();
}
}
break;
}
//调用mH的handleMessage
mH.handleMessage(msg);
return true;
}
});
}catch (Exception e){
Log.e(TAG, "hookHandler:Exception " + e.getMessage() );
e.printStackTrace();
}
}
接下来调用看效果:
<!-- TragetActivity并没有在清单文件中 -->
<activity android:name=".StubActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//hook
HookActivityUtils.hookActivityManager(this);
HookActivityUtils.hookHandler();
Intent intent = new Intent(this,TargetActivity.class);
startActivity(intent);
}
}
//TragetActivity布局
<TextView
android:textSize="20sp"
android:text="这是目标activity,TragetActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
//StubActivity布局
<TextView
android:textSize="20sp"
android:text="这个是代理activity,StubActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
如果看日志的话,会发现mActivityCallbacks.size() == 0,原因是Activity的生命周期方法会回调到EXECUTE_TRANSACTION统一处理,所以启动和销毁都有size == 0的情况
E/=====: handleMessage: mActivityCallbacks= []
E/=====: handleMessage: mActivityCallbacks= [WindowVisibilityItem{showWindow=true}]
E/=====: handleMessage: mActivityCallbacks= [LaunchActivityItem{intent=Intent { cmp=com.simple.bzm0518/.StubActivity (has extras) },ident=68590014,info=ActivityInfo{9ec475a com.simple.bzm0518.StubActivity}]
E/=====: handleMessage: mActivityCallbacks= []
效果图.png
还有另外一种简单的方案是Hook Instrumentation,后续再更新
Github : https://github.com/bzm0518/HookAMS
网友评论