Android Hook系列之寫個Hook練練手

背景

最近開始研究雙開迷殿,發(fā)現(xiàn)很多還是要用到代理一類的東西庆寺,先來研究下Proxy

什么是Proxy

動態(tài)代理(以下稱代理),利用Java的反射技術(shù)(Java Reflection)懦尝,在運行時創(chuàng)建一個實現(xiàn)某些給定接口的新類(也稱“動態(tài)代理類”)及其實例(對象)

(Using Java Reflection to create dynamic implementations of interfaces at runtime)。

作用

可以HOOK接口琅轧,直接修改實現(xiàn)的方法 踊挠, 在實現(xiàn)方法中加點料 。
想要學(xué)習(xí)一些基礎(chǔ)內(nèi)容可以看看這個文章 Hook系列之反射

實現(xiàn)一個簡單的HOOK試試

下面我們來實現(xiàn)一個Hook掉startActivity效床,使得每次調(diào)用這個方法,輸出一個日志剩檀。
首先看下startActivity的源碼。

@Override
public void startActivity(Intent intent, Bundle options) {
    warnIfCallingFromSystemProcess();
    if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
        throw new AndroidRuntimeException(
                "Calling startActivity() from outside of an Activity "
                + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                + " Is this really what you want?");
    }
    mMainThread.getInstrumentation().execStartActivity(
        getOuterContext(), mMainThread.getApplicationThread(), null,
        (Activity)null, intent, -1, options);
}

這里辐啄,實際上使用了ActivityThread類的mInstrumentation成員的execStartActivity方法运嗜;注意到,ActivityThread 實際上是主線程士复,而主線程一個進(jìn)程只有一個,因此這里是一個良好的Hook點阱洪。

接下來想辦法把mInstrumentation替換成我們修改過的代理對象。
首先我們要拿到主線程對象的應(yīng)用冗荸。ActivityThread類里面有一個靜態(tài)方法currentActivityThread可以幫助我們拿到這個對象類;但是ActivityThread是一個隱藏類盔粹,我們需要用反射去獲取程癌,代碼如下:

// 先獲取到當(dāng)前的ActivityThread對象
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);

拿到這個對象后,我們需要修改它的mInstrumentation這個字段為我們的代理對象嵌莉,我們先實現(xiàn)這個代理對象,由于JDK動態(tài)代理只支持接口中鼠,而這個Instrumentation是一個類沿癞,沒辦法,我們只有手動寫靜態(tài)代理類椎扬,覆蓋掉原始的方法即可。

public class EvilInstrumentation extends Instrumentation {

    private static final String TAG = "EvilInstrumentation";

    // ActivityThread中原始的對象, 保存起來
    Instrumentation mBase;

    public EvilInstrumentation(Instrumentation base) {
        mBase = base;
    }

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

        // Hook之前, XXX到此一游!
        Log.d(TAG, "\n執(zhí)行了startActivity, 參數(shù)如下: \n" + "who = [" + who + "], " +
                "\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +
                "\ntarget = [" + target + "], \nintent = [" + intent +
                "], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");

        // 開始調(diào)用原始的方法, 調(diào)不調(diào)用隨你,但是不調(diào)用的話, 所有的startActivity都失效了.
        // 由于這個方法是隱藏的,因此需要使用反射調(diào)用;首先找到這個方法
        try {
            Method execStartActivity = Instrumentation.class.getDeclaredMethod(
                    "execStartActivity",
                    Context.class, IBinder.class, IBinder.class, Activity.class, 
                    Intent.class, int.class, Bundle.class);
            execStartActivity.setAccessible(true);
            return (ActivityResult) execStartActivity.invoke(mBase, who, 
                    contextThread, token, target, intent, requestCode, options);
        } catch (Exception e) {
            // 某該死的rom修改了  需要手動適配
            throw new RuntimeException("do not support!!! pls adapt it");
        }
    }
}

后面就比較簡單了晶府,只要把原來的getInstrumentation()的方法里的mInstrumentation替換掉就可以了钻趋。

public static void attachContext() throws Exception{
    // 先獲取到當(dāng)前的ActivityThread對象
    Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
    Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
    currentActivityThreadMethod.setAccessible(true);
    Object currentActivityThread = currentActivityThreadMethod.invoke(null);

    // 拿到原始的 mInstrumentation字段
    Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
    mInstrumentationField.setAccessible(true);
    Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);

    // 創(chuàng)建代理對象
    Instrumentation evilInstrumentation = new EvilInstrumentation(mInstrumentation);

    // 偷梁換柱
    mInstrumentationField.set(currentActivityThread, evilInstrumentation);
}

這個方法只要在Activity的attachBaseContext去調(diào)用即可

   @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
        try {
            // 在這里進(jìn)行Hook
            attachContext();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

點擊下按鈕調(diào)用下一個Activity就可以了


image.png

Hook成功了蛮位。 成功的輸出了日志鳞绕。

進(jìn)階 Hook AMS的startActivity

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末们何,一起剝皮案震驚了整個濱河市萄焦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茬射,老刑警劉巖冒签,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異萧恕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)朴读,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門走趋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吆视,你說我怎么就攤上這事∧酰” “怎么了授滓?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長般堆。 經(jīng)常有香客問我,道長淮摔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任仔燕,我火速辦了婚禮魔招,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘办斑。我一直安慰自己,他們只是感情好鳞疲,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著建丧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橄维。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天争舞,我揣著相機(jī)與錄音澈灼,去河邊找鬼。 笑死叁熔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遭贸。 我是一名探鬼主播心软,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼删铃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咒劲,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤诫隅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后阎肝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肮街,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年沛硅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摇肌。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡围小,死狀恐怖昵骤,靈堂內(nèi)的尸體忽然破棺而出肯适,到底是詐尸還是另有隱情,我是刑警寧澤框舔,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站樱溉,受9級特大地震影響纬凤,放射性物質(zhì)發(fā)生泄漏福贞。R本人自食惡果不足惜移斩,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一向瓷、第九天 我趴在偏房一處隱蔽的房頂上張望肠套。 院中可真熱鬧猖任,春花似錦、人聲如沸朱躺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽源请。三九已至枪芒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纽甘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工悍赢, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留货徙,地道東北人。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓涮总,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瀑梗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容