在 某段子App協議分析(三) 這篇文章裏面,我們用frida rpc調用的方式來實現了某段子App的段子爬蟲,但是在實際使用的過程中,我們發現有如下兩個問題:
- frida不是很穩定,偶爾會崩潰退出
- 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
- 下載nanohttpd-2.3.1.jar 放到Android項目中的libs目錄下。
-
在 /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,就可以正常獲取數據了。
1:bashrc
三、總結
Xposed RPC比frida RPC穩定,如果線上環境使用的話,還需要增加一個看門狗程序,當某段子App異常退出之後,可以及時的把某段子App再調起來。