Xposed rpc + NanoHTTPD 案例NanoHTTPD

 某段子App協議分析(三) 這篇文章裏面,我們用frida rpc調用的方式來實現了某段子App的段子爬蟲,但是在實際使用的過程中,我們發現有如下兩個問題:

  1. frida不是很穩定,偶爾會崩潰退出
  2. flask服務是運行在pc上,所以還需要一臺pc一直開機

所以我們最好能實現在Android手機中運行一個穩定的web服務,然後把 手機的端口通過路由器映射出去,這樣就可以在任意環境下來調用簽名服務了。

Note:

  • Xposed rpc調用
  • NanoHTTPD
  • 手機端口映射到公網ip

二、分析

Xposed模塊的開發方法可以參照 最新的Xposed模塊編寫教程2020,在xposed中調用App中的靜態函數使用 XposedHelpers.callStaticMethod:

public static Object callMethod(Object obj, String methodName, Object... args)

public static Object callMethod(Object obj, String methodName, Class<?>[] parameterTypes, Object... args)

public static Object callStaticMethod(Class<?> clazz, String methodName, Object... args)

public static Object callStaticMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes, Object... args)

我們以調用 com.izuiyou.network.NetCrypto.getProtocolKey 爲例:

Class<?> clazzZy = null;
try {
        // 首先獲取 com.izuiyou.network.NetCrypto類
        clazzZy = loadPackageParam.classLoader.loadClass("com.izuiyou.network.NetCrypto");
        log("load class:" + clazzZy);
} catch (Exception e) {
        log("load class err:" + Log.getStackTraceString(e));
        return newFixedLengthResponse("load class is null");
}

// 然後調用 getProtocolKey
String rc = (String) XposedHelpers.callStaticMethod(clazzZy, "getProtocolKey");

調用函數完成之後,我們需要啓動一個http服務來把數據傳輸出來,這裏使用 NanoHTTPD

  1. 下載nanohttpd-2.3.1.jar 放到Android項目中的libs目錄下。
  2.  /app/build.gradle 文件的dependencies段增加

      compileOnly 'org.nanohttpd:nanohttpd:2.3.1’

1、2步也可以試試合併成直接在 /app/build.gradle 文件的dependencies段增加

  implementation'org.nanohttpd:nanohttpd:2.3.1'

Tip:

最後記得NanoHTTPD需要添加網絡權限

 <uses-permission android:name="android.permission.INTERNET"/>

然後我們創建一個myHttpServer類來啓動http服務

import java.io.IOException;
import fi.iki.elonen.NanoHTTPD;

class myHttpServer extends NanoHTTPD {

public myHttpServer() throws IOException {
        // 端口是8088,也就是說要通過http://127.0.0.1:8088來訪當問
        super(8888);
        start(NanoHTTPD.SOCKET_READ_TIMEOUT, true);
        log("---fenfei Server---");
}

@Override
public Response serve(IHTTPSession session) {
        // log("serve");
        //這個就是之前分析,重寫父類的一個參數的方法,
        //這裏邊已經把所有的解析操作已經在這裏執行了
        return super.serve(session);
}

@Override
public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {

        // 獲取類
        Class<?> clazzZy = null;
        try {
                clazzZy = loadPackageParam.classLoader.loadClass("com.izuiyou.network.NetCrypto");
                log("load class:" + clazzZy);
        } catch (Exception e) {
                log("load class err:" + Log.getStackTraceString(e));
                return newFixedLengthResponse("load class is null");
        }

        // 判斷是否是getkey請求
        if (StringUtils.containsIgnoreCase(uri, "getkey")) {//判斷uri是否正確
        return getKey(clazzZy);
        }

        // 判斷是否是setkey請求,並且取出post過來的數據
        if (StringUtils.containsIgnoreCase(uri, "setkey")) {//判斷uri是否正確
                String postData = files.get("postData");
                if (!StringUtils.isEmpty(postData)) {//判斷post過來的數據是否正確
                        return setkey(clazzZy,postData);
                }else{
                        return newFixedLengthResponse("postData is null");
                }
        }
}

public Response setkey(Class<?> clazzUse,String strKey){
        XposedHelpers.callStaticMethod(clazzUse, "setProtocolKey",strKey);
        log("setkey = "+strKey);
        return newFixedLengthResponse("set key ok");
}

}

// 創建httpServer實例
new myHttpServer();

把上次從frida RPC獲取簽名的地址 http://127.0.0.1:5000 改成新的xposed RPC的地址 http://192.168.2.102:8888,就可以正常獲取數據了。

rc

1:bashrc

三、總結

Xposed RPC比frida RPC穩定,如果線上環境使用的話,還需要增加一個看門狗程序,當某段子App異常退出之後,可以及時的把某段子App再調起來。

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