Heim >Betrieb und Instandhaltung >Sicherheit >So holen Sie sich das APK-Netzwerkpaket in Frida

So holen Sie sich das APK-Netzwerkpaket in Frida

WBOY
WBOYnach vorne
2023-05-16 19:16:381497Durchsuche

1. Konzentrieren Sie sich auf die Analyse der Fallstricke.

Suchen Sie aus Systemsicht nach Hook-Punkten, anstatt Pakete zu erfassen, um sie zu erfassen.

1.okhttp-Aufrufprozess

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)

2. Die Fallstricke, auf die Frida während des Analyseprozesses gestoßen ist (die wichtigsten Punkte finden Sie in den Kommentaren)

  1. 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打印
  2. 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");
    }
    };
  3. 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.

  1. 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调用概率比较大,但是不一定对网络进行请求
  2. Fängt den Ort ab, an dem JSON verwendet wird, bevor die App eine HTTP-Anfrage aufruft. Dies ist nur eine davon $Builder Interception

  3. property_get interception

  4. 2. Umgang mit Benutzerablauf aufgrund der Android_ID
  5. 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

  6. Analyse des ADB-Protokolls, der Prozess hat java.security.cert.CertPathValidatorException gedruckt, und ich habe bereits einige Beiträge über das Abfangen von Paketen und das Umgehen von Zertifikaten durch Frida gesehen. Versuchen Sie zunächst eine Brute-Force-Suche:
  7. 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

    rrree
  8. , um die Signatur neu zu packen und auszuführen, und die App kann sich diesmal normal anmelden. Die SSL-Überprüfung der App erfolgt nur in eine Richtung Der Server funktioniert nicht. Es wird keine Überprüfung durchgeführt.

4. Ende

Ich habe von Dienstagnachmittag bis Freitag gekämpft. Schließlich ist es keine gute Methode, Hook-Punkte von HttpEngine auf Systemebene zu finden, und die Nachteile sind bereits klar. Daher habe ich am Sonntag Paketerfassungstools und verschiedene Methoden von Baidu verwendet, um die aufgetretenen Probleme schrittweise zu lösen.

Hier sind die beiden gefangenen Tüten:

var 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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen