Hook技術之hookActivity(android 9.0)

1.前言

本文大部分內容來自於《android進階解密》這本書,不同的是書中實現的是android9.0之前的hook,在android9.0中,activity的啓動過程會有些不同,因此本文主要是講解9.0的hook.

2.activiy啓動流程的不同之處

1.簡要分析不同之處

在android9.0中,採用handler機制啓動activity時,消息標識變爲了EXECUTE_TRANSACTION,和之前的LAUNCH_ACTIVITY不同,並且msg攜帶的內容也不同,從這裏可以看到ClientTransaction transaction=msg.obj和之前msg攜帶的ActivityRecord參數不同,transaction裏邊並沒有Intent這個類型的變量
那麼我們能像書上一樣在此hook嗎?
答案是可以的,爲什麼沒有intent也能hook呢?看下邊分析

我們沿着調用鏈一直深入,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()方法中

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.

2.代碼

AMS動態代理類,IActivityManagerProxy

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;

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類,主要是還原intent

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就成功了

3.思考

其實hookActivity主要就是繞過AMS的驗證,因此在調用AMS的startActivity方法之前,都可以進行intent的替換,在AMS過後都可以進行intent的還原,因此有很多種hook方法,比如hook,Instrumatention進行intent的替換,對於intent的還原,目前我只想到在handlerMeassage中進行還原,因爲ActivityThread中有一個靜態變量sCurrentActivityThread,可以獲取activitythread對象,從而可以改變mH這個變量,或許還有更好的hook點。

今年年初我花一個月的時間收錄整理了一套知識體系,如果有想法深入的系統化的去學習的,可以私信我【安卓】,我會把我收錄整理的資料都送給大家,幫助大家更快的進階。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章