Hook技术之hookActivity(android 9.0)

1.前言

本文大部份内容来自于《android进阶解密》这本书,不一样的是书中实现的是android9.0以前的hook,在android9.0中,activity的启动过程会有些不一样,所以本文主要是讲解9.0的hook.android

2.activiy启动流程的不一样之处

1.简要分析不一样之处

在android9.0中,采用handler机制启动activity时,消息标识变为了EXECUTE_TRANSACTION,和以前的LAUNCH_ACTIVITY不一样,而且msg携带的内容也不一样,从这里能够看到ClientTransaction transaction=msg.obj和以前msg携带的ActivityRecord参数不一样,transaction里边并无Intent这个类型的变量
那么咱们能像书上同样在此hook吗?
答案是能够的,为何没有intent也能hook呢?看下边分析 bash

handleMessage
咱们沿着调用链一直深刻, mTransactionExecutor.execute(transaction)

接着调用 executeCallbacks(transaction)方法
executeCallback方法中,调用 item.execute方法,这个item为:

final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
 ···
 final ClientTransactionItem item = callbacks.get(i);
复制代码

那么这个item的类型为ClientTransactionItem,这是个抽象类,必须找到它的一个实现类,还记得这个callback吗?在activity的启动流程中,在ActivityStackSupeisor中的realStartActivityLocked()方法中app

clienttransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent).说明上面提到的 itemlaunchActivityItem,同时这个 LaunActiviyItem也确实为 ClientTransactionItem的一个子类,而且 LaunchActivityItem中也存在着 Intent这个变量,那么咱们的hook点也找到了

2.hook点

transaction中存在变量private List<ClientTransactionItem> mActivityCallbacks;,mActivityCallbacks中的元素为LaunchActivityItem,在LaunchActivityItem中存在变量private int mIdent;所以咱们仍是在ActivityThread.handleMessage时进行hook,不过要调用两次反射才能找到intent.ide

2.代码

AMS动态代理类,IActivityManagerProxyui

public class IActivityManagerProxy implements InvocationHandler {
    private Object activityManager;
    private static final String TAG="IActivityManagerProxy";
    public IActivityManagerProxy(Object activityManager){
        this.activityManager=activityManager;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equals("startActivity")){
            Intent intent =null;
            int index=0;
            for(int i=0;i<args.length;i++){
                if(args[i] instanceof Intent){
                    index=i;
                    break;
                }
            }
            intent = (Intent) args[index];
            String packageName = "com.suny.hooktest";
            Intent subIntent = new Intent();
            //替换activity为已经注册的占坑activity
            subIntent.setClassName(packageName,packageName+".SubActivity");
            //同时将真正的intent保存在subintent中,绕过AMS的检查后,将真正的intent替换回来
            subIntent.putExtra("target_intent",intent);
            args[index]=subIntent;
            Log.d(TAG, "invoke: subIntent="+subIntent+"inteent="+intent);
        }
        return method.invoke(activityManager,args);
    }
}

复制代码

HookerHelp类,主要是替换启动过程当中的'IActivityManager'为上边咱们本身的代理类,和为ActivityThread中的mH(Handler)添加callbacks;this

public class HookHelper {
    private static  final String TAG="HookHelper";
    public static void hookAms() throws Exception {
        Class clazz = ActivityManager.class;
        Field singletonIAMS = clazz.getDeclaredField("IActivityManagerSingleton");
        singletonIAMS.setAccessible(true);
        Object defultSingleton = singletonIAMS.get(null);
        Class singletonClazz = Class.forName("android.util.Singleton");
        Field mInstance = singletonClazz.getDeclaredField("mInstance");
        mInstance.setAccessible(true);
        Object iAMs = mInstance.get(defultSingleton);
        Class iAmClazz =Class.forName("android.app.IActivityManager");
        Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{iAmClazz},new IActivityManagerProxy(iAMs));
        mInstance.set(defultSingleton,proxy);
    }
    public static void hookHandler() throws Exception{
        Class acThreadClazz = Class.forName("android.app.ActivityThread");
        Field currentActivityThread = acThreadClazz.getDeclaredField("sCurrentActivityThread");
        currentActivityThread.setAccessible(true);
        Object currThread = currentActivityThread.get(null);
        Field mHField = acThreadClazz.getDeclaredField("mH");
        mHField.setAccessible(true);
        Handler mH = (Handler) mHField.get(currThread);
        Field mCallback = Handler.class.getDeclaredField("mCallback");
        mCallback.setAccessible(true);
        //为mH,添加mCallback,那么mH在handleMessage时,就会走咱们本身定义的callback中的handleMessage方法
        mCallback.set(mH,new HCallback(mH));
    }
}
复制代码

HCallbacks类,主要是还原intentspa

public class HCallback implements Handler.Callback{
    private final String TAG="HCallback";
    private Handler mHandler;
    public HCallback(Handler handler){
        mHandler=handler;
    }
    @Override
    public boolean handleMessage(Message msg) {
        //这里为159,是由于EXECUTE_TRANSACTION字段的值为159
        if(msg.what==159){
            //r实际为clienttransaction
            Object r= msg.obj;
            try {
                Class clientClazz = r.getClass();
                Field fCallbacks = clientClazz.getDeclaredField("mActivityCallbacks");
                fCallbacks.setAccessible(true);
                //获得transactionz中的callbacks,为一个list,其中元素为LaunActivityItem
                List<?> lists = (List) fCallbacks.get(r);
                for(int i=0;i<lists.size();i++){
                    Object item = lists.get(i);
                    Class itemClazz = item.getClass();
                    //拿到LaunActivityItem中的intent,进行替换
                    Field mIntent = itemClazz.getDeclaredField("mIntent");
                    mIntent.setAccessible(true);
                    Intent intent = (Intent) mIntent.get(item);
                    Intent target = intent.getParcelableExtra("target_intent");
                    if(target!=null){
                        intent.setComponent(target.getComponent());
                    }
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        mHandler.handleMessage(msg);
        return true;
    }
}

复制代码

定义一个本身的ApplicationattachBaseContext中初始化.代理

public class MyApplication extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        try {
            HookHelper.hookAms();
            HookHelper.hookHandler();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

hook就成功了code

3.思考

其实hookActivity主要就是绕过AMS的验证,所以在调用AMS的startActivity方法以前,均可以进行intent的替换,在AMS事后均可以进行intent的还原,所以有不少种hook方法,好比hook,Instrumatention进行intent的替换,对于intent的还原,目前我只想到在handlerMeassage中进行还原,由于ActivityThread中有一个静态变量sCurrentActivityThread,能够获取activitythread对象,从而能够改变mH这个变量,或许还有更好的hook点。cdn

相关文章
相关标签/搜索