Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Bagaimana untuk merebut pakej rangkaian apk di frida

Bagaimana untuk merebut pakej rangkaian apk di frida

WBOY
WBOYke hadapan
2023-05-16 19:16:381418semak imbas

1. Fokus pada menganalisis perangkap

Cari mata kait dari perspektif sistem, bukannya menangkap paket demi menangkapnya.

1.proses panggilan okhttp

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();
}
}

Kod penting klien adalah pada client.newCall(). Bermula dari panggilan antara muka di sini, ia akhirnya akan dipanggil ke rangka kerja okhttp pada asalnya ialah SDK Kemudian, AOSP telah disepadukan ke dalam sistem, jadi ia boleh diklasifikasikan ke dalam lapisan rangka kerja.

Lapisan rangka kerja tidak terperinci, terutamanya kelas java berikut:

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

Malah, client.newCall akhirnya akan mendapatkan sambungan melalui URL

HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

urlConnection di sini ialah sebenarnya Contoh HttpURLConnectionImpl Kelas ini mempunyai kaedah getInputStream getOutputStream, yang secara dalaman memanggil getBufferedRequestBody dan getResponse HttpEngine. Pada mulanya, saya cuba mengaitkan dua antara muka ini Contohnya, selepas mengaitkan getResponse, respons boleh dicetak.

Kemudian saya mendapati Permintaan hanya boleh mengeluarkan pengepala, bukan badan. Jadi saya melibatkan diri dalam analisis dan mendapati bahawa fungsi getBufferedRequestBody boleh digunakan untuk mendapatkan sink. Akhirnya, RetryableSink digunakan sebagai titik terobosan Sebagai contoh, mengaitkan fungsi tulisnya boleh mencetak badan. Fungsi tulis sepadan dengan urlConnection.getOutputStream().tulis pada peringkat aplikasi.

Kemudian saya menemui Permintaan, dan fungsi getBufferedReuqestBody mungkin dipanggil lebih daripada sekali, jadi akan ada masalah penduaan data Kemudian, saya menemui CacheStrategy$Factory.get point to hook, dan mendapati bahawa terdapat masih pertindihan data. Didapati bahawa semua cangkuk di atas mempunyai kelemahan

  • Penduaan data

  • panggilan bukan okhttp tidak boleh ditangkap

Kemudian timbunan panggilan bermula dari hantar, sendmsg, tulis, recv, dan baca lapisan asli juga dicetak. Selepas bergelut selama tiga hari, saya memutuskan untuk berhenti merawat dan menggunakan alat sebaliknya.

okhttp流程:sdk接口->okhttp框架->native(libc)

2. Perangkap yang dilalui frida semasa proses analisis (perkara utama ada dalam ulasan)

  1. android.util.Log tidak mencetak

    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. Kelas dalaman tanpa nama memerlukan renungan untuk mendapatkan ahli

    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. pencetakan Android.os.Bundle, Bundle perlu dipisahkan

    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);
    };

Sebenarnya, perangkap yang disebutkan di atas bukanlah satu-satunya perangkap yang saya temui Pada mulanya, saya juga telah mencuba beberapa penyelesaian pemintas rangkaian frida Saya juga mengkaji dengan teliti penyelesaian Interceptor okhttp bahawa apl itu juga menggunakan pemintas, jadi konflik berlaku dan penyelesaiannya tidak dapat digunakan .

Saya juga menganalisis smali apl semata-mata, mencari timbunan panggilan dan permintaan rangkaian Pada akhirnya, terdapat hanya beberapa keuntungan yang agak kecil, yang mungkin tidak berguna kepada pembaca, tetapi saya merekodkannya supaya saya boleh mengingati mereka kemudian.

  1. java.net.URL pemintasan

    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. Pemintasan tempat di mana json digunakan sebelum apl memanggil permintaan http, ini hanya satu daripadanya

    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. jejaki kelas berkaitan http

    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() {
    }
    });
    });
    };
  4. Request$Builder interception

    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;
    }
  5. property_get pemintasan

    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);
    }
    });

2. Menangani tamat tempoh pengguna akibat android_id peranti

var DEBUG_PROP = false;
var DEVICE_CONFIG = "/sdcard/.device";

function getVirtualDevice() {
var nativeOpen = new NativeFunction(Module.findExportByName(‘libc.so’, 'open'), 'int', ['pointer', 'int']);
var nativeRead = new NativeFunction(Module.findExportByName('libc.so', 'read'), 'int', ['int', 'pointer', 'int']);
var fd = nativeOpen(Memory.allocUtf8String(DEVICE_CONFIG), 0);
var mem = Memory.alloc(1024);
var readLen = nativeRead(fd, mem, 1024);
var json = JSON.parse(mem.readCString(readLen));
return json;
}

Secure.getString.implementation = function () {
var retval = this.getString(arguments[0], arguments[1]);
if (DEBUG_PROP) Logd(TAG, "Settings.Secure get " + arguments[1] + " val " + retval);

if (arguments[1].indexOf("android_id") != -1) {
var virtualDevice = getVirtualDevice();
return virtualDevice.android_id;
}

return retval;
};

3 >

1. Tetapan proksi biola adalah OK, aplikasi Tetapi tidak dapat log masuk

Menganalisis log adb, proses tersebut mempunyai java.security.cert.CertPathValidatorException Saya juga telah melihat beberapa siaran tentang memintas frida paket dan memintas sijil sebelum ini. Cuba carian brute force dahulu:

Java.perform(function(){
const groups = Java.enumerateMethods('*!verify/u');
var classes = null;
for(var i in groups){
var classes = groups[i]['classes'];

for(var i in classes){
Java.use(classes[i]['name'])
.verify
.overload('java.lang.String', 'javax.net.ssl.SSLSession')
.implementation = function() {
printBacktrace();
LOG("[+] invoke verify", { c: Color.Red });
return true;
}
}
}
});
Walaupun anda secara langsung memaksa pengesahan untuk mengembalikan benar, anda masih tidak boleh log masuk kerana ralat masalah SSL yang sama berlaku. Saya menemui jawapannya selepas mencari di Baidu. Buka bungkusan apktool, kemudian ubah suai

res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<!--添加fiddle证书可信任
<certificates src="user" />
-->
</trust-anchors>
</base-config>
</network-security-config>
untuk membungkus semula tandatangan dan menjalankannya dan apl boleh log masuk seperti biasa kali ini pengesahan, pelayan tidak melakukan pengesahan.

4. Berakhir

Saya terus bergelut dari petang Selasa hingga Jumaat Akhirnya, mencari mata kait dari HttpEngine di peringkat sistem bukanlah kaedah yang baik, dan keburukan sudah jelas. Oleh itu, pada hari Ahad, saya menggunakan alat tangkapan paket dan pelbagai kaedah yang terdapat pada Baidu untuk menyelesaikan masalah yang dihadapi secara beransur-ansur.

Berikut ialah dua beg yang ditangkap:

HTTP/1.1 200 OK
Date: Sun, 16 Aug 2020 06:27:34 GMT
Content-Type: application/json
Content-Length: 101
Connection: keep-alive
Grpc-Metadata-Content-Type: application/grpc
Vary: Origin
Vary: Accept-Encoding

{"result":{"errno":"OK","errmsg":"成功"},"data":{"version":"xxxxxxxx-351e-40cf-aaa9-3177d6df9b7f"}}
-----------------------------------
HTTP/1.1 200 OK
Date: Sun, 16 Aug 2020 06:27:34 GMT
Content-Type: application/json
Content-Length: 99
Connection: keep-alive
Grpc-Metadata-Content-Type: application/grpc
Vary: Origin
Vary: Accept-Encoding

{"result":{"errno":"OK","errmsg":"成功"},"data":{"nodeToken":"xxxxxxxc24d79f55c0b07beaf50cb566"}}
POST https://tap-xxxxxxx.xxxxxx.com/api/v2/Android/analytics/basic HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cjbcjdsabcjvbXVCJ9.eyJ1aWQiOjE4ODMzMDEsInNlY3JldCI6IjAzNzE0M2Y3LTExMTUtNGY2Yi1iNzQxLWUyMjc5ZDM3MGY3MCIsImV4cCI6MTU5NzgxNjQ0MiwiaXNzIjoiZ3Vlc3QgbG9naW4ifQ.W3SiO0-afbhxPITjRinnhyWhZLy1bzZhYexm5VCWklI
X-Device-ID: 9xxxxxxx84d4542e
X-Loc: ["China","Shanghai","Shanghai","","ChinaUnicom","31.224349","121.4767528","Asia/Shanghai","UTC+8","310000","86","CN","AP","xxx.166.xxx.xxx"]
X-App-Version: 2.2.0
Content-Type: application/json; charset=utf-8
Content-Length: 208
Host: xx-xxxx.xxxxxx.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.7.2

{"deviceID":"9xxxxxxx84d4542e","model":"V1813BA","systemVersion":"9","version":"2.2.0","location":{"latitude":xx.x99x990990991,"longitude":xxx.26689769073256},"network":{"g2":0,"g3":0,"g4":4,"g5":0,"wifi":4}}

-----------------------------------
HTTP/1.1 200 OK
Date: Sun, 16 Aug 2020 06:27:35 GMT
Content-Type: application/json
Content-Length: 43
Connection: keep-alive
Grpc-Metadata-Content-Type: application/grpc
Vary: Origin
Vary: Accept-Encoding

{"result":{"errno":"OK","errmsg":"成功"}}

Atas ialah kandungan terperinci Bagaimana untuk merebut pakej rangkaian apk di frida. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam