Heim >Betrieb und Instandhaltung >Sicherheit >So holen Sie sich das APK-Netzwerkpaket in Frida
Suchen Sie aus Systemsicht nach Hook-Punkten, anstatt Pakete zu erfassen, um sie zu erfassen.
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(url) .post(body) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } }
Der wichtige Code des Clients befindet sich auf client.newCall(). Das Obige ist ein Beispiel von der offiziellen Website von okhttp. Ausgehend vom Schnittstellenaufruf wird schließlich das okhttp-Framework aufgerufen. Okhttp ist ursprünglich ein SDK. Später wurde AOSP in das System integriert, sodass es in die Framework-Ebene eingeordnet werden kann.
Die Framework-Ebene ist nicht detailliert, hauptsächlich diese Java-Klassen:
com.android.okhttp.internal.huc.HttpURLConnectionImpl com.android.okhttp.internal.http.HttpEngine com.android.okhttp.internal.http.RetryableSink com.android.okhttp.internal.http.CacheStrategy$Factory
Tatsächlich erhält client.newCall schließlich eine Verbindung über die URL
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
Die URLConnection hier ist tatsächlich eine Instanz von HttpURLConnectionImpl. Diese Klasse hat den getInputStream getOutputStream Methode werden intern getBufferedRequestBody und getResponse von HttpEngine aufgerufen. Zuerst habe ich versucht, diese beiden Schnittstellen zu verknüpfen. Nach dem Verknüpfen von getResponse kann die Antwort beispielsweise ausgedruckt werden.
Später habe ich festgestellt, dass Request nur Header, aber keinen Text ausgeben kann. Also habe ich mich in die Analyse vertieft und festgestellt, dass die Funktion getBufferedRequestBody verwendet werden kann, um eine Senke zu erhalten. Schließlich kann RetryableSink als Durchbruchspunkt verwendet werden, um beispielsweise den Text auszudrucken. Die Schreibfunktion entspricht urlConnection.getOutputStream().write auf App-Ebene.
Später entdeckte ich, dass die Funktion getBufferedReuqestBody für eine Anfrage möglicherweise mehr als einmal aufgerufen wurde, sodass es zu einem Problem der Datenduplizierung kam. Später fand ich den CacheStrategy$Factory.get-Punkt zum Hooken und stellte fest, dass dies immer noch der Fall war Datenvervielfältigung. Es wurde festgestellt, dass alle oben genannten Hooks Nachteile haben
Datenduplizierung
Nicht-OKhttp-Anrufe können nicht erfasst werden
Dann beginnt der Aufrufstapel mit Senden, Senden, Schreiben, Empfangen und Lesen der nativen Ebene wurde auch gedruckt. Nachdem ich drei Tage lang gekämpft hatte, beschloss ich schließlich, die Behandlung aufzugeben und stattdessen Werkzeuge zu verwenden.
okhttp流程:sdk接口->okhttp框架->native(libc)
android.util.Log wird nicht gedruckt
var Logd = function Logd(tag, msg) { Java.use("android.util.Log").d(tag, msg); }; Logd('http-body-', '11111111111111');//该log不打印 Logd('http-body', '11111111111111');//该log打印
Anonyme innere Klassen erfordern Reflexion, um Mitglieder zu erhalten
var printRequest = function(request) { var Buffer = Java.use("com.android.okhttp.okio.Buffer"); var bodyField = request.getClass().getDeclaredField('body'); bodyField.setAccessible(true); if (request == null) return; Logd('http', 'printRequest: request' + request); //var requestBody = request.body();//gadget直接报错 var requestBody = bodyField.get(request); var requestBodyClass = requestBody.getClass(); var ClassInstanceArray = Java.array('java.lang.Class', []); //var contentLengthMethod = requestBodyClass.getMethod("contentLength");//gadget直接报错 var contentLengthMethod = requestBodyClass.getMethod("contentLength", ClassInstanceArray); contentLengthMethod.setAccessible(true); var ObjectInstanceArray = Java.array('java.lang.Object', []); var contentLength = requestBody ? contentLengthMethod.invoke(requestBody, ObjectInstanceArray) : 0; //if (contentLength == 0) contentLength = contentLen; Logd('http', 'printRequest contentLength: ' + contentLength); if (contentLength > 0) { var BufferObj = Buffer.$new(); requestBody.writeTo(BufferObj); Logd(TAG, "\nrequest body :\n" + BufferObj.readString() + "\n"); } };
Beim Drucken von os.Bundle müssen Sie das Bundle entpacken
var printIntentAndExtras = function printIntentAndExtras(intentObj) { if (intentObj == null) return; var Intent = Java.use("android.content.Intent"); var Bundle = Java.use("android.os.Bundle"); var bundleObj = Intent.getExtras.call(intentObj); if (bundleObj != null) { Bundle.getSize.call(bundleObj, null);//调用getSize即可反序列化 } Logd(TAG, ‘printIntentAndExtras ’ + bundleObj); };
Tatsächlich sind die oben genannten Fallstricke nicht die einzigen Fallstricke, die ich ausprobiert habe Ich habe auch die Interceptor-Lösung von okhttp sorgfältig untersucht und schließlich festgestellt, dass die App auch verwendet. Der Interceptor ist deaktiviert, sodass ein Konflikt auftritt und die Lösung nicht verwendet werden kann.
Ich habe auch nur die Smali der App analysiert und nach dem Call-Stack und den Netzwerkanfragen gesucht. Am Ende gab es nur ein paar relativ kleine Gewinne, die für die Leser vielleicht nicht nützlich sind, aber ich habe sie aufgezeichnet, damit ich sie nutzen kann erinnern Sie sich später daran.
java.net.URL-Abfangen
var URLHook = function() { var URL = Java.use('java.net.URL'); URL.openConnection.overload().implementation = function() { var retval = this.openConnection(); Logd('URL', openConnection' + retval); return retval; }; };//URL.openConnection调用概率比较大,但是不一定对网络进行请求
Fängt den Ort ab, an dem JSON verwendet wird, bevor die App eine HTTP-Anfrage aufruft. Dies ist nur eine davon $Builder Interception
var jsonHook = function() { var xx = Java.use('e.h.a.a');//app smali var xxa_method = xx.a.overload('org.json.JSONObject', 'java.lang.String', 'java.lang.String'); xxa_method.implementation = function(jsonObj, str1, str2) { Logd("json", jsonObj + " str1: " + str1 + " str2" + str2); xxa_method.call(this, jsonObj, str1, str2); } }
3. Verwenden Sie das Paketerfassungstool, um Pakete zu erfassen und aus der Grube herauszukommen Die Fiddle-Proxy-Einstellung ist in Ordnung, aber die App kann sich nicht anmelden
var traceAllHttpClass = function() { Java.perform(function() { Java.enumerateLoadedClasses({ onMatch: function(name, handle) { /*"e.h.a.a$a",起初也拦截过app的该混淆类*/ if (name.indexOf("com.android.okhttp.Http") != -1 || name.indexOf("com.android.okhttp.Request") != -1 || name.indexOf("com.android.okhttp.internal") != -1) { traceClass(name);//对这三个class进行trace } }, onComplete: function() { } }); }); };
Selbst wenn Sie die Überprüfung direkt erzwingen, um „true“ zurückzugeben, können Sie sich immer noch nicht anmelden, da der gleiche SSL-Problemfehler auftritt. Ich habe die Antwort gefunden, nachdem ich auf Baidu gesucht habe. Entpacken Sie apktool, ändern Sie dann
rrreevar BuilderClass = Java.use('com.android.okhttp.Request$Builder') BuilderClass.build.implementation = function () { //LOG('com.android.okhttp.HttpUrl$Builder.build overload', { c: Color.Light.Cyan }); //printBacktrace(); var retval = this.build(); Logd(TAG, "retval:" + retval); printRequest(retval); return retval; }
var nativePropertyGetAddr = Module.findExportByName(null, '__system_property_get'); Interceptor.attach(nativePropertyGetAddr, { onEnter: function onEnter(args) { this._name = args[0].readCString(); this._value = args[1]; }, onLeave: function onLeave(retval) { if (this._name.indexOf("ro.build.id") != -1) { var virtualDevice = getVirtualDevice(); if (DEBUG_PROP) Logd(TAG, "__system_property_get fake " + this._name + "=>to " + virtualDevice.build_id); this._value.writeUtf8String(virtualDevice.build_id); } var strFilter = /^ro\./g; if (DEBUG_PROP && this._name.match(strFilter) != null) Logd(TAG, "__system_property_get " + this._name); } });
Das obige ist der detaillierte Inhalt vonSo holen Sie sich das APK-Netzwerkpaket in Frida. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!