從Android視角看數據爬蟲

從Android視角看數據爬蟲

簡介

從Android客戶端視角看數據爬蟲,主要分爲以下幾個步驟
1、通過反編譯等手段,hook住對應app的網絡請求庫,得到對應的URL
2、根據hook的點打印出當時的header和參數
3、模擬APP請求,發起對應的數據請求

如何實現

通過反編譯和Hook獲取url

這個爬蟲的重點步驟,通過此步驟才能的到對應的URL,難易程度取決於APP對自己的保護程度。主要從以下幾種情況來說明:


1、使用了OkHttp,但未自己進行封裝或修改的:

直接通過hook OkHttp的addInterceptoer方法即可隨意往裏添加自己定義的interceptoer方法,由於此方法會將整個chain(請求鏈)作爲參數,因此我們添加到最後即可獲取所有的請求信息並打印出來。

現在大部分的私人app或者小公司app通過此方法即可輕鬆獲取url、header和參數等信息。



2、使用了OkHttp,但對其中的實現進行了修改:

此情況如果沒有混淆,可以找到修改後添加Interrupter的方法,並進行hook方法插入。其餘同方案1。

如果混淆了,可以先找到添加Interrupter的方法,但過程比較麻煩,需要好很多經歷。或同方案3.



3、對於自己封裝或者對OkHttp修改比較大的,Android可以直接HOOK網絡底層,直接hook到請求和數據返回的地方,獲取對應的url和參數。

此方法比較麻煩,不同的Android版本,對於請求的封裝並不相同。

使用XPosed來hook請求,獲取URL和參數

hook到OkHttp的buid方法,然後將自定義的interceptor添加到interceptors中。

    XposedHelpers.findAndHookMethod(instanceClazz, "build", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                synchronized (OkHttpHook.class){
                    if (hasHooked){
                        return;
                    }
                    hasHooked = true;
                    LOGGER.d("正在運行build方法,開始hook");
                    List interceptors = (List) XposedHelpers.getObjectField(param.thisObject, "interceptors");

                    if (interceptors != null){
                        //如果獲取到了interceptors
                        LOGGER.d("interceptors = "+interceptors.size());
                        Object logInterceptor = getLoggingInterceptor();
                        if (logInterceptor != null){
                            //獲取到了interceptor
                            LOGGER.d("獲取到Log的interceptor");
                            interceptors.add(logInterceptor);
                        }
                        LOGGER.d("interceptors = "+interceptors.size());
                        LOGGER.e("has been hooked succeed!");
                    }
                }
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
            }
        });

    /**
     * 獲取jar包中的interceptor
     * @return
     */
    private Object getLoggingInterceptor() {
        String jarPath = FileUtils.PATH_FILE_DIR + File.separator + FileUtils.FILE_NAME_INTERCEPTOR;
        LOGGER.d("當前jarPath="+jarPath);
        File file = new File(jarPath);
        if (file.exists()){
            LOGGER.d("存在interceptor的jar文件");
        }
        DexClassLoader dexClassLoader = new DexClassLoader(jarPath, FileUtils.PATH_OUT_DIR, null, mClassLoader);
        try {
            mHttpLoggingInterceptor = dexClassLoader.loadClass("com.alzzz.interceptor.AlzInterceptor");
            mLoggerClass = dexClassLoader.loadClass("com.alzzz.interceptor.AlzInterceptor$Logger");
            if (mLoggerClass != null && mHttpLoggingInterceptor != null) {
                LOGGER.e("獲取到jar包中的攔截器");
                return InitInterceptor();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

具體的interceptor隨自己心願,想寫什麼寫什麼,類需要實現Interceptor接口,方法中可以獲取chain對象,這個能做的事情就有很多了。拿到url和參數很輕鬆。

模擬請求,獲取數據

使用第二步獲取到的url和header及params,進行模擬數據請求。如果此時的request鑑權通過,即可繞過獲取數據。

https證書問題

以上方案,除了模擬請求都可以完全繞過證書,不受證書控制。Android手機在root後使用XPose可以繞過證書鑑權,獲取請求數據。

怎麼防禦

從客戶端出發

1、監聽進程,判斷是否有Xpose的運行進程,如果有則直接彈出提示,不讓對方使用。

現在市面上很多APP都做了這項處理,但是,不能完全防禦,因爲XPosed可以hook自己把自己進程也變了

2、加殼
使用第三代的加密方式,對自己的apk進行加密,大大加強反編譯和hook難度。

XPosed可以hook到Android系統然後將轉成的SO庫從系統中導出出來,加大反編譯成本,而且會替換掉部分代碼,是的可讀性更差。

3、使用更加噁心的混淆方式0o0o00這樣的加密方式,大大降低可讀性。

從Server出發

1、除了信安的鑑權方式外,爲每個接口都增加業務鑑權。

對比與閒魚,每次請求閒魚會不斷修改

wua=HHnB_xFKMPecU%2BxPA%2FNwVHVrwPQq7O83RzZawsAN%2FgEb2fGizfJ%2FWZU6SC%2BxxVPx4VI1K0noc2g8gpji27DUg9uleZNA169x2z8zyYSc8RaeBRaXSAszUK90P%2FI%2BkH5mVXD%2F%2B<br>
x-sign=ab23180010e22f50c705640041863ba451bb884b3cd0aad85f<br>

每次請求都會進行修改,這裏就可以推斷出,每次鑑權都會根據一個雙方協定好的加密方式,對每次請求的唯一標示進行了加密。例如:


時間戳+用戶id+關鍵某幾個過程中不可修改的參數+私鑰(或對稱加密方式的隨機串)



進行了一次加密。Server根據這次請求唯一的加密鑑權,確定是否返回數據。

成本:每次請求都需要進行加密串的生成,確認是對哪些參數進行加密。



2、如果請求就是從客戶端發起的,直接是模擬的客戶端真實的點擊

該情況,很難避免,只能加大其成本,如果間隔頻率太小的請求,劃入到異常請求,如果達到某個量級則對deviceId進行封禁。

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