2023-10-05

編寫Xposed模塊

了解完Xposed框架的相關(guān)知識后,我們還要編寫一些模塊代碼梗摇,才能實現(xiàn)我們的監(jiān)測操作。
首先在gradle里面依賴一下xposed的api:

compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'

在進(jìn)行Xposed模塊開發(fā)之前格遭,我們有必要了解一下Xposed API愚铡。完成一個模塊的開發(fā)至少有兩步要做:

1、編寫一個java類并實現(xiàn)**IXposedHookLoadPackage**接口幔摸,實現(xiàn)**handleLoadPackage**方法進(jìn)行自定義的監(jiān)測操作
2摸柄、注冊這個java類

編寫代碼

假如我們需要監(jiān)測的方法是:
[圖片上傳失敗...(image-819ac2-1696475692002)]
那么,我們的初始方法就可以寫成這個樣子:

public class HookTrack implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {

    }
}

handleLoadPackage中既忆,調(diào)用XposedHelpers類的findMethodHook來進(jìn)行驱负,在寫代碼的時候,我們發(fā)現(xiàn)其實有兩個方式可以選用:
[圖片上傳失敗...(image-219c78-1696475692002)]
區(qū)別在于第一個方法傳入的是class本體患雇,然后源碼那邊使用的classLoader就是class.getClassLoader;第二種不需要class本體跃脊,只需要指定這個class的名字,然后再指定加載這個class的classLoader苛吱。從便捷上來說酪术,第一種無疑是便捷的。但是第二種的靈活度比第一種高翠储。假如有一些類是第三方SDK里面的绘雁,而這個SDK沒在你源碼里面橡疼,是以插件形式在你app安裝完后才加進(jìn)來的。這時候咧七,你在編碼階段是沒有辦法得到這個class本體的衰齐,所以第二種方法可以看作是能hook運(yùn)行時的class,并且官方注釋還給出了第二種的使用模式:
[圖片上傳失敗...(image-c3e6d8-1696475692002)]
因此继阻,按照官方提供的思路耻涛,我們可以這樣寫:

XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getDeviceId",
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId()獲取了imei");
                    }
                }
        );

注意到我們最后的那個回調(diào)函數(shù)XC_methodHook,
[圖片上傳失敗...(image-4ef009-1696475692002)]
首先,這是一個抽象類瘟檩,不是接口抹缕。beforeHookMethodafterHookMethod從字面意思也能看出是在hook前后的調(diào)用回調(diào)。然后其構(gòu)造函數(shù)有兩個墨辛,有一個是帶int類型的卓研,傳入的是一個設(shè)置hook優(yōu)先級的數(shù)字。
[圖片上傳失敗...(image-7e38fd-1696475692002)]
從方法注釋上看睹簇,這個priority會影響后面beforeHookMethodafterHookMethod的調(diào)用順序奏赘。優(yōu)先級越高的Hook,其beforeHook方法會越先執(zhí)行,然后其afterHook方法會在最后執(zhí)行太惠。如果存在hook多個方法磨淌,且所有的priority都相同,會依次此執(zhí)行完這個方法的before和after在執(zhí)行下一個方法的before和after凿渊,以此類推梁只。
而采用無參構(gòu)造的,其priority是一個系統(tǒng)默認(rèn)值50:
[圖片上傳失敗...(image-1a4b70-1696475692002)]
假如我們Hook了3個方法A,B,C埃脏。在priority相同和不同時的調(diào)用關(guān)系可以參考下圖:

[圖片上傳失敗...(image-1d1204-1696475692002)]
知道了上面的原理后搪锣,我們就應(yīng)該選用默認(rèn)或者相同priority的方式來進(jìn)行hook。
扯了這么多彩掐,大家也別嫌麻煩构舟,工欲善其事,必先利其器《掠模現(xiàn)在再回到之前的代碼旁壮。我們在beforeHookMethod里面調(diào)用了

XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId()獲取了imei");

XposedBridge也是rovo89開發(fā)的一個Xposed的輔助庫,調(diào)用其log方法后可以在手機(jī)端的Xposed管理器里面顯示相關(guān)信息谐檀,這一步的意思表示我們監(jiān)測了app調(diào)用android.telephony.TelephonyManager這個類的getDeviceId方法

打印方法調(diào)用棧

上面的所有操作知識標(biāo)記了調(diào)沒調(diào)用指定的方法抡谐。但是如果調(diào)用了,是誰調(diào)用的桐猬,其實我們時不清楚的麦撵。這樣其實不利于我們查找問題的根源。回看本文的第一張信通院的圖免胃,發(fā)現(xiàn)他們檢測時音五,其實給了方法調(diào)用棧。那么我們現(xiàn)在就來模擬一下這種操作羔沙。
我們需要打印的是整個hook期間的方法棧躺涝,那么這個操作就應(yīng)該放在afterHookMethod里面,于是扼雏,我們可以寫成這樣:

XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getDeviceId",
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId()獲取了imei");
                    }

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        //在這里寫調(diào)用方法棧過程
                    }
                }
        );

日志打印的話自然還是用到XposedBridgelog方法坚嗜。由于我們需要hook的方法不止一個,而我們打印方法調(diào)用棧又是一樣的操作诗充,于是乎我們可以自己寫一個抽象類繼承XC_MethodHook,只實現(xiàn)afterMethodHook方法苍蔬,在里面做統(tǒng)一的方法棧追蹤操作。因此蝴蜓,我們先自定義一個DumpMethodHook的類碟绑,代碼如下:

public abstract class DumpMethodHook extends XC_MethodHook {

    /**
     * 該方法會在Hook了指定方法后調(diào)用
     * @param param
     */
    @Override
    protected void afterHookedMethod(MethodHookParam param) {
        //在這里,我們dump一下調(diào)用的方法棧信息
        dump2();
    }

    /**
     * dump模式一:根據(jù)線程進(jìn)行過濾
     */
    private static void dump() {
        for (Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStackTraces().entrySet()) {
            Thread thread = (Thread) stackTrace.getKey();
            StackTraceElement[] stack = (StackTraceElement[]) stackTrace.getValue();
            // 進(jìn)行過濾
            if (thread.equals(Thread.currentThread())) {
                continue;
            }
            XposedBridge.log("[Dump Stack]" + "**********線程名字:" + thread.getName() + "**********");
            int index = 0;
            for (StackTraceElement stackTraceElement : stack) {
                XposedBridge.log("[Dump Stack]" + index + ": " + stackTraceElement.getClassName()
                        + "----" + stackTraceElement.getFileName()
                        + "----" + stackTraceElement.getLineNumber()
                        + "----" + stackTraceElement.getMethodName());
            }
            // 增加序列號
            index++;
        }
        XposedBridge.log("[Dump Stack]" + "********************* over **********************");
    }

    /**
     * dump模式2:類信通院報告模式
     */
    private static void dump2(){
        XposedBridge.log("Dump Stack: "+"---------------start----------------");
        Throwable ex = new Throwable();
        StackTraceElement[] stackElements = ex.getStackTrace();
        if (stackElements != null) {
            for (int i= 0; i < stackElements.length; i++) {
                StringBuilder sb=new StringBuilder("[方法棧調(diào)用]");
                sb.append(i);
                XposedBridge.log("[Dump Stack]"+i+": "+ stackElements[i].getClassName()
                        +"----"+stackElements[i].getFileName()
                        +"----" + stackElements[i].getLineNumber()
                        +"----" +stackElements[i].getMethodName());
            }
        }
        XposedBridge.log("Dump Stack: "+ "---------------over----------------");
    }
}

通過查詢資料茎匠,我寫了兩種方法棧打印的操作格仲。第一種打印得比較細(xì)一些,但是實際測試要卡頓一點(diǎn)诵冒。第二種就和信通院報告差不多了凯肋,而且沒有明顯卡頓。
寫好了自定義的回調(diào)造烁,這時我們只需要將前面的XC_MethodHook替換為DumpMethodHook即可:

XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getDeviceId",
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId()獲取了imei");
                    }
                }
        );

需要監(jiān)測的方法

既然合規(guī)這件事情是工信部搞出來的否过,那么我們自然要看一下當(dāng)時的這份紅頭文件——工信部信管函「164號文」
下面是我目前整理出來的需要hook的一些方法:

方法名字 所屬包名 作用
getDeviceId android.telephony.TelephonyManager 獲取設(shè)備號
getDeviceId(int) android.telephony.TelephonyManager getDeviceId的帶參版本
getImei android.telephony.TelephonyManager 安卓8增加的獲取IMEI的方法
getImei(int) android.telephony.TelephonyManager getImei的帶參版本
getSubscriberId android.telephony.TelephonyManager 獲取IMSI
getMacAddress android.net.wifi.WifiInfo 獲取MAC地址
getHardwareAddress java.net.NetworkInterface 獲取MAC地址
getString android.provider.Settings.Secure 獲取系統(tǒng)相關(guān)信息字符來拼接deviceId
getLastKnownLocation LocationManager 獲取GPS定位信息
requestLocationUpdates LocationManager 位置午笛、時間發(fā)生改變的時候獲取定位信息

上面的方法信息可能不全惭蟋,如果大家有更好的意見可以留言。我看網(wǎng)上很多資料是沒有對requestLocationUpdates和安卓8的新增方法getImei進(jìn)行監(jiān)控的药磺,這里我加了進(jìn)來告组。

對Hook的APP進(jìn)行過濾,設(shè)置白名單

一般來講癌佩,你的手機(jī)安裝的不止一個app木缝。如果用上面的代碼去監(jiān)測,實際會監(jiān)測你手機(jī)上所有的app围辙。這就導(dǎo)致日志會很雜亂我碟,我們其實只關(guān)心指定的app。因此我們需要設(shè)置一個白名單進(jìn)行過濾:

/**
  * 需要Hook的包名白名單
  */
 private static final String[] whiteList = {
         "com.cjs.drv",
         "com.cjs.hegui30.demo"
 };

里面填寫的就是你需要監(jiān)測的app的包名姚建。
然后我們在HandleLoadPackage方法的最開始矫俺,寫一段過濾的操作:

/*判斷hook的包名*/
boolean res = false;
for (String pkgName : whiteList) {
    if (pkgName.equals(lpparam.packageName)) {
        res = true;
        break;
    }
}
if (!res) {
    Log.e(TAG, "不符合的包:" + lpparam.packageName);
    return;
}

最終,貼上一個成品的代碼:

public class HookTrack implements IXposedHookLoadPackage {
    private static final String TAG = "HookTrack";

    /**
     * 需要Hook的包名白名單
     */
    private static final String[] whiteList = {
            "com.cjs.drv",
            "com.bw30.zsch",
            "com.bw30.zsch.magic",
            "com.cjs.hegui30.demo"
    };

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {

        if (lpparam == null) {
            return;
        }

        Log.e(TAG, "開始加載package:" + lpparam.packageName);
        /*判斷hook的包名*/
        boolean res = false;
        for (String pkgName : whiteList) {
            if (pkgName.equals(lpparam.packageName)) {
                res = true;
                break;
            }
        }
        if (!res) {
            Log.e(TAG, "不符合的包:" + lpparam.packageName);
            return;
        }

        //固定格式
        XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(), // 需要hook的方法所在類的完整類名
                lpparam.classLoader,                            // 類加載器,固定這么寫就行了
                "getDeviceId",                     // 需要hook的方法名
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId()獲取了imei");
                    }
                }
        );
        XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getDeviceId",
                int.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getDeviceId(int)獲取了imei");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getSubscriberId",
                int.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getSubscriberId獲取了imsi");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getImei",
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getImei獲取了imei");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                android.telephony.TelephonyManager.class.getName(),
                lpparam.classLoader,
                "getImei",
                int.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getImei(int)獲取了imei");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                android.net.wifi.WifiInfo.class.getName(),
                lpparam.classLoader,
                "getMacAddress",
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getMacAddress()獲取了mac地址");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                java.net.NetworkInterface.class.getName(),
                lpparam.classLoader,
                "getHardwareAddress",
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getHardwareAddress()獲取了mac地址");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                android.provider.Settings.Secure.class.getName(),
                lpparam.classLoader,
                "getString",
                ContentResolver.class,
                String.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用Settings.Secure.getstring獲取了" + param.args[1]);
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                LocationManager.class.getName(),
                lpparam.classLoader,
                "getLastKnownLocation",
                String.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用getLastKnownLocation獲取了GPS地址");
                    }
                }
        );

        XposedHelpers.findAndHookMethod(
                LocationManager.class.getName(),
                lpparam.classLoader,
                "requestLocationUpdates",
                String.class,
                new DumpMethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        XposedBridge.log(lpparam.packageName + "調(diào)用requestLocationUpdates獲取了GPS地址");
                    }
                }
        );
    }
}

注冊模塊代碼

上面的操作到目前為止也只是在你的安卓項目中添加了一個java類厘托。如何讓xposed識別到我們寫的代碼是個xposed模塊呢友雳?這就需要注冊一下這個類。
注冊分兩步操作:
1铅匹、在AndroidManifest.xml中編寫meta信息

<!--  標(biāo)志該 apk 為一個 Xposed 模塊押赊,供 Xposed 框架識別-->
<meta-data
    android:name="xposedmodule"
    android:value="true" />

<!--模塊說明,一般為模塊的功能描述-->
<meta-data
    android:name="xposeddescription"
    android:value="這個模塊是用來檢測用戶隱私合規(guī)的包斑,在用戶未授權(quán)同意前流礁,調(diào)用接口獲取信息屬于違規(guī)" />

<!--模塊兼容版本-->
<meta-data
    android:name="xposedminversion"
    android:value="54" />

在application節(jié)點(diǎn)里面加上這三個meta信息。那個說明會最終顯示在xposed管理器上面:
[圖片上傳失敗...(image-beb013-1696475692002)]
注意:填寫meta信息是標(biāo)記我們這個apk是個xposed模塊的關(guān)鍵舰始,否則xposed installer不會識別崇棠。

2、在項目asset文件夾下面新建xposed_init文件
[圖片上傳失敗...(image-d81e84-1696475692002)]
在里面寫上我們實現(xiàn)IXposedHookLoadPackage那個類的包名+類名

com.cjs.hegui30.HookTrack

這樣我們就寫好了自定義的xposed模塊丸卷。Xposed在加載的時候會從這個文件里面讀取需要初始化的類枕稀。
至此,我們的所有代碼就編寫完成了谜嫉,此時裝在手機(jī)后萎坷,可以在xposed installer里面識別激活了。

其他

源碼同時捆綁了一個快速測試的demo和相關(guān)的apk文件沐兰,demo可以單獨(dú)編譯成apk,記得切換
[圖片上傳失敗...(image-9f72eb-1696475692002)]
[圖片上傳失敗...(image-dae7f9-1696475692002)]


操作手冊

一哆档、準(zhǔn)備條件

1、編譯合規(guī)檢測的Xposed模塊源碼

下載源碼住闯,修改設(shè)置白名單瓜浸,編譯成apk,安裝到手機(jī)
相關(guān)操作參考《安卓端自行實現(xiàn)工信部要求的隱私合規(guī)檢測一(教你手寫Xposed模塊代碼)》

注意:源碼里面包含了各種安裝包及demo

2比原、已經(jīng)root的手機(jī)可以下載Xposed.apk

Xposed在github上面開源插佛,可以自己下載XposedInstaller的源碼進(jìn)行編譯,也可以直接下載已經(jīng)編譯好的apk量窘。

需要注意的是雇寇,安卓5以上和以下的安裝版本是不一樣的
支持安卓5及以上的XposedInstaller
支持安卓5以下的XposedInstaller

3、沒有root的手機(jī)可以下載VirtualXposed.apk

VirtualXposed在github上面有專門的release頁面蚌铜,其作者在0.20.x的版本的時候放棄了對32位應(yīng)用的支持锨侯,理由是谷歌商店未來只允許64位的app上架,不想花更多精力維護(hù)32位的開發(fā)冬殃。如果你的app為32位應(yīng)用囚痴,因此不能用0.20.x及之后版本的VirtualXposed

0.20.3版本(支持64位應(yīng)用)
0.18.2版本(支持32位應(yīng)用)
注意:由于0.20.x版本更換了包名,所以它和0.18.x的版本能同時安裝

4审葬、下載合規(guī)檢測測試程序

該項非必須深滚,僅作為合規(guī)快速校驗

下載地址:合規(guī)檢測測試程序apk


二骂束、具體操作

這里以對“合規(guī)檢測測試程序“的校驗進(jìn)行說明。

1展箱、安裝

  • 已root的用戶
 1. 安裝xposed.apk

在root手機(jī)上安裝xposed框架的操作可能會比較麻煩混驰,詳情問問度娘

 2. 安裝合規(guī)檢測xposed模塊.apk
 3. 安裝合規(guī)檢測測試程序.apk
  • 未root用戶
 1. 先安裝virtual-xposed.apk
 2. 后續(xù)操作有兩種方案:

第一種可以和已root用戶一樣,直接將合規(guī)檢測xposed模塊.apk和合規(guī)檢測測試程序.apk安裝在手機(jī)真機(jī)上栖榨,然后在virtual-xposed里面克隆這兩個app;
第二種的話就是不在真機(jī)裝明刷,直接在virtual-xposed里面裝婴栽,具體操作如下:

  1. 打開virtual-xposed,點(diǎn)擊底部的菜單按鈕轰枝,進(jìn)入到virtual-xposed的菜單界面
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715095447417.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖1" align=center />
    </div>

  2. 在菜單界面有兩個關(guān)鍵點(diǎn)需要注意鞍陨,一個是頂部的添加應(yīng)用,一個是底部的重啟寿烟。后者在激活模塊的時候需要使用韧衣。這里我們先點(diǎn)擊添加應(yīng)用氏淑。
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715100616238.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖2" align=center />
    </div>

  3. 添加應(yīng)用界面默認(rèn)的tab項就是克隆APP,如果使用克隆的方式的話缭贡,就要先找到安裝的合規(guī)檢測xposed模塊和合規(guī)檢測測試程序谍失,并勾選快鱼,然后選擇底部的安裝;如果選擇的是虛擬機(jī)安裝窃判,就直接點(diǎn)擊右下角的加號按鈕袄琳,選擇本地的apk安裝包進(jìn)行安裝。
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715101257676.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖3" align=center />
    </div>

  4. 在克隆APP中窗轩,會彈出是否使用太極安裝,我們還是選擇virtual-xposed安裝
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715101819206.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖4" align=center />
    </div>

  5. 安裝完app后堤舒,下一步就是激活模塊。我們返回到1中的界面国撵,上滑,進(jìn)入到app列表界面环础,在這里可以看見我們剛剛安裝的3個app
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715102701144.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖5" align=center />
    </div>

  6. 最右邊的那邊Xposed Installer就是我們的xposed控制界面 饶唤,點(diǎn)擊進(jìn)入搬素。大大的綠勾表示我們的xposed框架已經(jīng)激活。點(diǎn)擊左上角三杠粱哼。
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715102939132.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖6" align=center />
    </div>

  7. 在彈出來的菜單界面中有兩個項要注意:模塊用于安裝/卸載xposed模塊,日志用于查看合規(guī)檢測的結(jié)果绊含,后面會用到。這里我們點(diǎn)擊模塊充甚。
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715103119338.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖7" align=center />
    </div>

  8. 可以看見有一個合規(guī)檢測的xposed模塊,勾上它技矮。勾上后需要重啟系統(tǒng)。如果是root用戶在真機(jī)下操作xposed框架耿币,就需要真機(jī)重啟。但是我們用的是virtual-xposed塑悼,所以只需要重啟虛擬機(jī)就行了厢蒜。這時候,返回到2的界面巷屿,點(diǎn)擊重啟
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715103340219.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖8" align=center />
    </div>

  9. 重啟成功的話,底部會有提示語展示
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715103551253.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖9-1" align=center />
    <img src="https://img-blog.csdnimg.cn/20210715103629292.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖9-2" align=center />
    </div>

2问拘、如何檢測

  1. 先打開我們安裝的測試app

里面有四個按鈕,分別對應(yīng)四種不同的檢測條件或油,我們以第一種模擬獲取IMSI來說明,先別點(diǎn)擊任何按鈕辖佣。
<div align="center">

<img src="https://img-blog.csdnimg.cn/20210715103931453.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖10" align=center />

</div>

  1. 查看日志

回到我們在安裝講解中的第7步界面,里面有個日志選項端逼,點(diǎn)擊它顶滩。該界面右上角有保存按鈕,還有個三個點(diǎn)的菜單按鈕仅醇,點(diǎn)擊菜單按鈕后有兩個項需要注意:

  • 立即清理日志會清空當(dāng)前界面的所有日志,我們先點(diǎn)擊清空一下甲抖。
  • 重新載入會刷新最新的日志進(jìn)界面。因為日志的顯示不是自動的柱衔,要想看到最新的結(jié)果,就要手動刷新艾岂。
    <div align="center">
    <img src="https://img-blog.csdnimg.cn/20210715104617934.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖11-1" align=center />
    <img src="https://img-blog.csdnimg.cn/20210715104640552.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NqczE1MzQ3MTcwNDA=,size_16,color_FFFFFF,t_70" width = "300" alt="圖11-2" align=center />
    </div>

接下來回到我們的測試app界面梅猿,點(diǎn)擊模擬獲取IMSI钞啸,然后再返回到日志界面体斩,并且重新載入哨毁,接著就能看見如下的日志記錄:
[圖片上傳失敗...(image-19438-1696475692002)]

上面的截圖主要針對virtual-xposed來講的想幻。對于xposed而言脏毯,操作大同小異渣淤。最大的區(qū)別就是xposed需要真實地重啟手機(jī),這點(diǎn)的話要麻煩一點(diǎn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市惠奸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌共虑,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猜惋,死亡現(xiàn)場離奇詭異,居然都是意外死亡谍咆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門峭状,熙熙樓的掌柜王于貴愁眉苦臉地迎上來优床,“玉大人望忆,你說我怎么就攤上這事∏副福” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長利凑。 經(jīng)常有香客問我哀澈,道長膨报,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任辱揭,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘该编。我一直安慰自己硕淑,他們只是感情好置媳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布拇囊。 她就那樣靜靜地躺著寥袭,像睡著了一般杰扫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啤覆,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼杀糯。 笑死,一個胖子當(dāng)著我的面吹牛骂际,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了岸裙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尉剩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皂林,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年蚯撩,在試婚紗的時候發(fā)現(xiàn)自己被綠了础倍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沟启,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呀癣,到底是詐尸還是另有隱情美浦,我是刑警寧澤弦赖,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布项栏,位于F島的核電站,受9級特大地震影響蹬竖,放射性物質(zhì)發(fā)生泄漏沼沈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一币厕、第九天 我趴在偏房一處隱蔽的房頂上張望列另。 院中可真熱鬧,春花似錦旦装、人聲如沸页衙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽店乐。三九已至,卻和暖如春呻袭,著一層夾襖步出監(jiān)牢的瞬間眨八,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工左电, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廉侧,地道東北人页响。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像段誊,于是被迫代替她去往敵國和親闰蚕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

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