常見的Xposed框架檢測手段與突破方式

Xposed框架被很多人用來注入App做一些Hook操作,當然有相應的注入也必然存在對應的檢測(反調試)操作,之前在吾愛、看雪論壇上看到很多大佬花式突破Xposed檢測的手法,所以秉承“拿來主義”,匯總了一下各大App常見的Xposed的檢測手法和突破的方式(這里只講關于在Java層面檢測Xposed,深入到SO層作檢測之后再講)。

**Xposed檢測方案以及突破方式****

1. 遍歷App安裝列表檢測是否包含Xposed Installer

原理:當App獲取到系統權限的時候,可以獲取系統的所有運行中的App的列表,通過列表發現是否存在有Xposed相關的App(通常都是Xposed Installer相關的Apk,例如de.robv.android.xposed.installer)保持運行狀態,一旦存在,就表明用戶很有可能存在Hook行為。
解決方案:目前市面上的大多數手機廠都把應用權限暴露給用戶,所以用戶可以自定義App的權限,禁止相關的App獲取應用列表就可以防止App通過這個途徑檢測Xposed框架,當然,要過這個檢測可以修改Installer包名即可。

2. 通過自造異常檢測堆棧信息,讀取異常堆棧中是否包含Xposed字符串來識別

原理:在正常的Android系統啟動過程中,init進程會去解析init.rc文件啟動一系列的服務,其中就有app_process進程,在app_process執行過程中,會設置自身進程名為Zygote,啟動com.android.internal.os.ZygoteInit.Main方法。而Xposed修改了app_process進程,會先啟動de.robv.android.xposed.XposedBridge.Main方法,再由它去啟動com.android.internal.os.ZygoteInit.Main方法,因此堆棧信息中會多出一些內容。
簡單說就是Xposed先于了Zygote進程,因此在系統堆棧信息中會多出Xposed相關的內容。
解決方案:通過Hook堆棧類StackTraceElement,當發現Xposed和Zygote有錯誤輸出時,修改輸出信息,例如將輸出置空來繞過錯誤信息檢測。參考代碼:

XposedHelpers.findAndHookMethod(StackTraceElement.class, "getClassName", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                String result = (String) param.getResult();
                if (result != null) {
                    if (result.contains("de.robv.android.xposed.")) {
                        param.setResult("");                    
                    } else if (result.contains("com.android.internal.os.ZygoteInit")) {
                        param.setResult("");
                    }
                }
                super.afterHookedMethod(param);
            }
        });

3. 通過ClassLoader的 loadClass 加載列表檢測。

解決方案:通過Hook loadClass加載類來修改加載的類名,例如修改de.robv.android.xposed成另一個普通的包名參考代碼:

XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
            @Override

            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                if (param.args != null && param.args[0] != null && param.args[0].toString().startsWith("de.robv.android.xposed.")) {                     // 改成一個不存在的類                    
                    param.args[0] = "de.robv.android.xposed.ThTest";
                }
                super.beforeHookedMethod(param);
            }
        });

4. 由于Xposed的注入方式是通過底層SO文件修改被hook的方法為native來實現的,所以檢測方也可以通過檢測方法是否變成了native來達到檢測的目的。

原理:Xposed把Method的native func修改為它自己的處理函數,再這個函數中會回調Java層的handleHookMethod,處理函數鉤子,但是只有native函數,虛擬機才會走native func,所以Xposed會把java函數的修飾符修改為native,所以可以通過反射調用Modifier.isNative(method.getModifiers())方法可以校驗方法是不是native方法.
解決方案:因為檢測方必須要通過Modifier.isNative這個方式來做檢測,所以方法就是通過Hook isNative的方法,將檢測結果置為0就行

參考代碼:

modifyXposedHelpers.findAndHookMethod(Method.class, "getModifiers", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                Method method = (Method) param.thisObject;
                String[] array = new String[]{"getDeviceId"};
                String method_name = method.getName();
                if (Arrays.asList(array).contains(method_name)) {
                    modify = 0;
                } else {
                    modify = (int) param.getResult();
                }
                super.afterHookedMethod(param);
            }
        });
        XposedHelpers.findAndHookMethod(Modifier.class, "isNative", int.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                param.args[0] = modify;
                super.beforeHookedMethod(param);
            }
        });

5. 檢測Xposed相關文件

原理:通過讀取proc/self/maps文件,在linux內核中,這個文件存儲了進程映射了的內存區域和訪問權限,因此遍歷自身加載的庫,就可以拿到當前上下文的so和jar列表,通過查找Xposed相關文件來做檢測解決方案:因為讀取的時候會調用BufferedReader進行讀取命令的內容,我們只需要Hook BufferedReader過濾掉XposedBridge.jar等相關內容就可以完成繞過。
參考代碼:

XposedHelpers.findAndHookMethod(BufferedReader.class, "readLine", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                String result = (String) param.getResult();
                if (result != null) {
                    if (result.contains("/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar")) {
                        param.setResult("");
                        new File("").lastModified();
                    }
                }
                super.afterHookedMethod(param);
            }
        });

6. 通過反射XposedHelper類和XposedBridge類做信息檢測

原理:Xposed中有幾個比較常用的方法,findAndHookMethod等。通過反射找到要Hook的函數后會保存到XposedHelper類中的fieldCache、methodCache、constructorCache字段中。因此,可以通過反射遍歷XposedHelper類中的fieldCache、methodCache、constructorCache變量,讀取HashMap緩存字段是否有被Hook App的關鍵函數信息就行解決方案:檢測方通過反射調用XposedHelper的成員fieldCache中是否含有相關的關鍵字。
解決方案:修改類名,讓檢測方找不到相關類就行,可以參考第三種方案,修改類名參考代碼。

總結:各種手段的目的,最終都是解決如何定位Xposed檢測代碼的問題,最有效的方案就是搜索相關的關鍵詞,例如上述幾種檢測方案中說的某些關鍵詞,其他方法待后續總結。
對于對抗xposed檢測的問題,也可以使用FakeXposed等框架,對特定機器的framework層,進行修改,然后再安裝程序,進行調試。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容