frida如何抓apk網路包
一 . 埋頭分析踩坑路
從系統的角度去尋找hook點,而不是為了抓包而抓包。
1.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(); } }
客戶端的重要程式碼在client.newCall()上,上面是okhttp官網的範例。從此處介面呼叫開始,終會呼叫至okhttp框架, okhttp本是sdk,後來aosp已經整合至系統,所以可以歸類至框架層。
框架層不詳述,主要就是這幾個java類別:
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
其實client.newCall終會透過URL取得一個connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
這裡的urlConnection其實就是HttpURLConnectionImpl的實例,該類別有getInputStream getOutputStream方法,內部分別會呼叫HttpEngine的getBufferedRequestBody,getResponse。剛開始我嘗試hook過這兩個接口,例如hook getResponse後,可以將response印出來.
後來我發現,Request只能輸出header,無法輸出body。所以又埋頭繼續分析,getBufferedRequestBody這個函數剛好可以入手,取得一個sink,最後以RetryableSink為突破點,例如hook 其write函數就可以將body印出來。 write函數對應於app層面的urlConnection.getOutputStream().write。
後來發現一個Request,呼叫getBufferedReuqestBody函數可能不只一次,所以會有資料重複的問題,後來我又尋找到了CacheStrategy$Factory.get點進行Hook,發現還是有資料重複。發現以上hook都有弊端
資料重複
#非okhttp呼叫無法抓取
okhttp流程:sdk接口->okhttp框架->native(libc)
- android.util.Log不印
var Logd = function Logd(tag, msg) { Java.use("android.util.Log").d(tag, msg); }; Logd('http-body-', '11111111111111');//该log不打印 Logd('http-body', '11111111111111');//该log打印
登入後複製 - 匿名內部類別取得成員需要反射
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"); } };
登入後複製 - android.os.Bundle列印,需要將Bundle unparcel
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); };
登入後複製
- java.net.URL攔截
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调用概率比较大,但是不一定对网络进行请求
登入後複製 - #攔截app呼叫http請求前使用json的地方,這只是其中之一
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); } }
登入後複製 - trace http相關class
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() { } }); }); };
登入後複製 - #Request$Builder攔截
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; }
登入後複製 - property_get攔截
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); } });
登入後複製
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;
};
登入後複製
三. 使用抓包工具fiddle抓包脫坑1.fiddle代理設定OK,app卻無法登陸分析adb log,進程有java.security.cert.CertPathValidatorException的列印,之前也看過一些frida攔截抓包繞過憑證的貼文。先試試一把暴力搜索:
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; };
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; } } } });
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>
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":"成功"}}
以上是frida如何抓apk網路包的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Google's AI assistant, Gemini, is set to become even more capable, if the APK teardown of the latest update (v15.29.34.29 beta) is to be considered. The tech behemoth's new AI assistant could reportedly get several new extensions. These extensions wi

作為一個滲透測試小白,本文的目的是希望能為那些和我一樣的小白提供一些測試想法。涉及的內容可能比較基礎,表哥們見諒。 APK解包拿到apk之後直接用7-Zip解壓縮可以得到幾個資料夾、一個AndroidManifest.xml檔、一個dex檔。使用dex2jarhttps://sourceforge.net/projects/dex2jar/將這個dex檔案解壓縮會產生一個jar文件,然後使用jd-gui就可以查看java原始碼了。當然可以從原始碼裡找程式碼的漏洞,但一般會有混淆,在這裡也不做深入討論。

您是否下載過以字母 APK 結尾的檔案?這通常發生在適用於手機並加載到您的電腦上的應用程式上。這些文件中的大多數都以字母 APK 結尾。您可能一直在嘗試打開這些文件,但由於它們不尋常的擴展名而無法弄清楚它們的存儲位置或如何打開它們。如果您正在尋找一種在 Windows 11 上開啟此類檔案的方法,並且已經透過 Google 搜尋了您的頭髮,請不要擔心!它實際上比這容易得多。事實上,這樣做是免費的,您甚至不需要安裝任何東西。好吧,你必須為你的作業系統下載一個 APK 檔案開啟器——但前提是你還沒

更改步驟:1、確保已經將要更改名稱的APK文件保存到電腦上;2、右鍵點擊APK文件,選擇「重新命名」選項;3、將原有的文件名稱替換為你想要的新名稱。確保只更改檔案名稱部分,而不要更改檔案的副檔名「.apk」;4、按Enter鍵或點擊視窗中的「重新命名」按鈕來儲存變更即可。

一.埋頭分析踩坑路從系統的角度去尋找hook點,而不是為了抓包而抓包。 1.okhttp呼叫流程publicstaticfinalMediaTypeJSON=MediaType.get("application/json;charset=utf-8");OkHttpClientclient=newOkHttpClient();Stringpost(Stringurl,Stringjson)throwsIOException{RequestBodybody=RequestBodyody

Unity3D程式的安全問題程式碼安全問題Unity3D程式的核心組件檔案Assembly-CSharp.dll是標準的.NET檔案格式,附帶了方法名稱、類別名稱、類型定義等豐富的元資料訊息,使用DnSpy等工具可以輕易地將其反編譯和篡改,程式碼邏輯、類別名稱和方法名等一覽無餘。程式碼邏輯一但被反編譯,很容易滋生各種類型的外掛,破壞遊戲平衡,如果程式碼邏輯中存在漏洞,也容易被挖掘和利用,可能對開發商造成無法預料的損失。資源安全性問題Unity3D程式在編譯打包階段會透過Unity編輯器將資源打包成AssetBun

眾所周知,微軟宣布了win11將能夠運行安卓應用程序,並且可以安裝本地apk,但是在更新win11之後用戶發現自己不知道怎麼安裝本地apk,其實是因為目前微軟還沒有為win11實裝這款功能,需要等待功能實裝才能使用。 win11怎麼安裝本地apk:1.根據微軟的說法,win11在實裝了這個功能之後,直接雙擊下載好的apk檔案就可以直接安裝了。 2.安裝完成後使用者也可以直接在系統中運作了。 3.雖然現在已經是正式版win11了,但微軟目前還沒有為win11實裝這個功能。 4.所以如果使用者想要在win11

一、前言apk在未加密的情況下,透過反編譯,得到smail檔。將需要注入的程式碼注入即可。之後封裝、簽名即可!二、製作apk使用androidstudio產生一個簡單的apk。使用預設代碼即可。 packagecom.example.myapplication1;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;publicclassMainActivityextendsAppCompatActivity{
