《吐血整理》高級系列教程-喫透Fiddler抓包教程(31)-Fiddler如何抓取Android系統中Flutter應用程序的包

1.簡介

Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生用戶界面。Flutter應用程序是用Dart編寫的,這是一種由Google在7年多前創建的語言。Flutter是Google使用Dart語言開發的移動應用開發框架,使用一套Dart代碼就能快速構建高性能、高保真的iOS和Android應用程序。

HTTP應用層的抓包已經成爲日常工作測試與調試中的重要一環,最近接觸新項目突然之間發現之前的抓包手段都不好使了,頓時模塊與模塊之間的前端與服務之間的交互都變成了不可見,整個人都好像被矇住了眼睛。

2.驗證是否走代理

Flutter 應用的網絡請求是不走手機的系統代理的,也就是說你在系統設置中設置了代理地址和端口號後 Flutter 也不會走你的代理,而抓包是必須要設置代理的,然後走代理我們纔可以成功的抓到包,現在人家都不從你這裏走,累死你都抓不到。

方法一:首先我們使用正常的抓包流程:通過fiddler進行抓包,可以看到,只抓到一些圖片和一些沒有用處的亂七八糟的文件,那麼很有可能他不走代理。

還有一種方法可以判斷APP是否爲無代理請求模式:以fiddler爲例,當我們配置好fiddler證書、模擬器wifi配置好ip和端口後,客戶端關閉fiddler抓包工具,如果該APP還可以正常運行說明請求爲無代理模式。

宏哥查了一下現在使用Flutter的應用程序,發現好多程序都用它,宏哥就選擇了某魚這一款APP。

按照之前的宏哥配置,模擬器配置了代理而且這個代理是走Fiddler的,如果宏哥沒有啓動Fiddler如果是走代理的應用程序,就會出現網絡問題,如果是不走代理的應用程序,就可以正常訪問網絡。具體操作步驟如下:

1.宏哥沒有啓動Fiddler,然後用瀏覽器訪問百度,出現網絡問題,因爲代理的網絡走到Fiddler這裏,Fiddler不通,出現網絡問題。如下圖所示:

2.宏哥沒有啓動Fiddler,然後啓動應用某魚APP,正常訪問網絡,因爲不走代理的網絡,Fiddler啓動不啓動對其沒有影響,不會出現網絡問題。如下圖所示:

通過以上對比,我們確認了這款某魚APP不走我們手機設置的代理,因此我們就不可能抓到它的包了。

3.爲什麼http請求沒有通過wifi走代理?

爲什麼http請求沒有通過wifi走代理呢,因爲之前安卓原生使用的一些http框架都是正常走代理的啊,那是不是有可能代碼中有api方法可以設置請求不走代理,於是乎就研讀了一下Flutter中http相關的源碼,最終找到了答案。

3.1http請求源碼跟蹤

http.dart中的HttpClient是一個抽象類,成員方法的具體實現在http_impl.dart中,http的get請求實現如下:

Future<HttpClientRequest> getUrl(Uri url) => _openUrl("get", url);

Future<_HttpClientRequest> _openUrl(String method, Uri uri) {

 .

 .

 .

 // Check to see if a proxy server should be used for this connection.

 var proxyConf = const _ProxyConfiguration.direct();

 if (_findProxy != null) {

 // TODO(sgjesse): Keep a map of these as normally only a few

 // configuration strings will be used.

 try {

 proxyConf = new _ProxyConfiguration(_findProxy(uri));

 } catch (error, stackTrace) {

 return new Future.error(error, stackTrace);

 }

 }

 return _getConnection(uri.host, port, proxyConf, isSecure)

 .then((_ConnectionInfo info) {

 .

 .

 .

 });

}

首先,我們可以發現方法中有一行註釋// Check to see if a proxy server should be used for this connection.,意思是“檢查是否應該使用代理服務器進行此連接”;

然後,有一個proxyConf對象初始化和根據_findProxy來創建新的proxyConf對象的語句,然後通過_getConnection(uri.host, port, proxyConf, isSecure)來創建連接,_getConnection的源碼如下:

Future<_ConnectionInfo> _getConnection(String uriHost, int uriPort,

 _ProxyConfiguration proxyConf, bool isSecure) {

 Iterator<_Proxy> proxies = proxyConf.proxies.iterator;

 Future<_ConnectionInfo> connect(error) {

 if (!proxies.moveNext()) return new Future.error(error);

 _Proxy proxy = proxies.current;

 String host = proxy.isDirect ? uriHost : proxy.host;

 int port = proxy.isDirect ? uriPort : proxy.port;

 return _getConnectionTarget(host, port, isSecure)

 .connect(uriHost, uriPort, proxy, this)

 // On error, continue with next proxy.

 .catchError(connect);

 }

 return connect(new HttpException("No proxies given"));

}

從代碼中我們可以看到根據代理配置信息來將請求的host和port進行重置,然後創建真實的連接。

跟蹤以上源碼我們發現dart中http請求是否走代理是需要配置的,而_findProxy變量和配置的代理信息有關。

http__impl.dart文件中的_HttpClient類中定義了_findProxy的默認值

Function _findProxy = HttpClient.findProxyFromEnvironment;

HttpClient類中findProxyFromEnvironment方法的實現

static String findProxyFromEnvironment(Uri url,

 {Map<String, String> environment}) {

 HttpOverrides overrides = HttpOverrides.current;

 if (overrides == null) {

 return _HttpClient._findProxyFromEnvironment(url, environment);

 }

 return overrides.findProxyFromEnvironment(url, environment);

}

_HttpClient類中_findProxyFromEnvironment方法的實現

static String _findProxyFromEnvironment(

 Uri url, Map<String, String> environment) {

 checkNoProxy(String option) {

 if (option == null) return null;

 Iterator<String> names = option.split(",").map((s) => s.trim()).iterator;

 while (names.moveNext()) {

 var name = names.current;

 if ((name.startsWith("[") &&

 name.endsWith("]") &&

 "[${url.host}]" == name) ||

 (name.isNotEmpty && url.host.endsWith(name))) {

 return "DIRECT";

 }

 }

 return null;

 }

 checkProxy(String option) {

 if (option == null) return null;

 option = option.trim();

 if (option.isEmpty) return null;

 int pos = option.indexOf("://");

 if (pos >= 0) {

 option = option.substring(pos + 3);

 }

 pos = option.indexOf("/");

 if (pos >= 0) {

 option = option.substring(0, pos);

 }

 // Add default port if no port configured.

 if (option.indexOf("[") == 0) {

 var pos = option.lastIndexOf(":");

 if (option.indexOf("]") > pos) option = "$option:1080";

 } else {

 if (option.indexOf(":") == -1) option = "$option:1080";

 }

 return "PROXY $option";

 }

 // Default to using the process current environment.

 if (environment == null) environment = _platformEnvironmentCache;

 String proxyCfg;

 String noProxy = environment["no_proxy"];

 if (noProxy == null) noProxy = environment["NO_PROXY"];

 if ((proxyCfg = checkNoProxy(noProxy)) != null) {

 return proxyCfg;

 }

 if (url.scheme == "http") {

 String proxy = environment["http_proxy"];

 if (proxy == null) proxy = environment["HTTP_PROXY"];

 if ((proxyCfg = checkProxy(proxy)) != null) {

 return proxyCfg;

 }

 } else if (url.scheme == "https") {

 String proxy = environment["https_proxy"];

 if (proxy == null) proxy = environment["HTTPS_PROXY"];

 if ((proxyCfg = checkProxy(proxy)) != null) {

 return proxyCfg;

 }

 }

 return "DIRECT";

}

從以上代碼中可以發現代理配置從environment中讀取,設置代理時必須指定http_proxy或https_proxy等。而從_openUrl方法實現中proxyConf = new _ProxyConfiguration(_findProxy(uri));得出默認情況下environment是爲空的,所以要想在Flutter的http請求中使用代理,則要指定相應的代理配置,即設置httpClient.findProxy的值。示例代碼:

_getHttpData() async {

 var httpClient = new HttpClient();

 httpClient.findProxy = (url) {

 return HttpClient.findProxyFromEnvironment(url, environment: {"http_proxy": 'http://192.168.124.7:8888',});

 };

 var uri =

 new Uri.http('t.weather.sojson.com', '/api/weather/city/101210101');

 var request = await httpClient.getUrl(uri);

 var response = await request.close();

 if (response.statusCode == 200) {

 print('請求成功');

 var responseBody = await response.transform(Utf8Decoder()).join();

 print('responseBody = $responseBody');

 } else {

 print('請求失敗');

 }

}

以上代碼設置後即可使用Fiddler或Charles抓包了。

敲黑板!!!代碼中已設置代理,手機wifi不再需要進行代理設置;192.168.124.7該IP爲我們需要抓包的Charles所在電腦IP。

查了好多資料絕大多數是在代碼中設置代理,或者是代碼設置了,然後讓其走手機代理,或許這對於開發很容易但是對於測試,或者別人家的APP或許就不是很容易了。下面我們看看下邊的方案。

4.使用VPN

使用VPN將終端設備的流量轉發到代理服務器。說的好聽點就是使用VPN,難聽點就是使用Drony工具強行使APP走代理。

優勢:使用VPN軟件不用添加其他測試。

劣勢:終端上的VPN默認會直接對所有流量進行轉發,要進行合理的配置可能需要額外的學習成本。

  因爲我們的測試對象是手機移動APP,因爲我們的測試對象是手機移動APP,所以我們首先要在手機上安裝一個VPN,這裏使用一個十分方便的VPN軟件drony (介紹在這裏https://github.com/SuppSandroB/sandrop/wiki/Drony-FAQ),drony會在你的手機上創建一個VPN,將手機上的所有流量都重定向到drony自身(不是流向vpn服務器) ,這樣drony就可以管理所有手機上的網絡流量,甚至可以對手機上不同APP的流量進行單獨配置。

4.1下載安裝Drony

1.下載對應的安裝包到手機上安裝好,宏哥這裏還是用夜神模擬器做演示,訪問其下載地址:https://drony.soft112.com/ 翻不了牆的,用這個地址下載:https://www.appsapk.com/drony-1-3-155/,如下圖所示:

 

2.下載安裝包並安裝好。安裝完成後打開軟件,如下圖所示:

4.2配置drony轉發

1.打開Drony(處於OFF狀態),切換到SETTINGS(無法點擊,試試左右滑動切換到SETTING),如下圖所示:

 

2.選擇Networks,點擊Wi-Fi,如下圖所示:

3.點擊Wi-Fi,進入配置界面,如果是真機或者你有多個熱點可以連接都可以在這裏顯示,這個就和我們手機連接WiFi一樣。在網絡列表中選擇點擊當前手機wifi連接的網絡 (需要確保該網絡與Fiddler代理服務器網絡是聯通的)。如下圖所示:

4.由於宏哥這裏是模擬器,因此需要宏哥編輯一下,在這界面選中那個VirtWifi(虛擬WiFi)長按,彈出Edit和Delete。如下圖所示:

5.點擊“Edit”。進入網絡詳情設置(Network details),如下圖所示:

6.設置代理hosetname,默認是電腦局域網ip,也就是Fiddler安裝電腦的IP,如下圖所示:

7.設置代理Port,fiddler 默認是 8888,如下圖所示:

8.設置 Proxy type,注意Proxy type代理方式要選擇 Plain http proxy。如下圖所示:

 敲黑板!!!!最上邊的Proxy type,選擇代理模式爲手動(Manual),如下圖所示:

9.設置Filter default value爲Direct all,如下圖所示:

10.設置Rules,點擊下面的Rule設置應用規則。如下圖所示:

11.點擊“Edit filter Rules”,。進入添加規則頁面,如下圖所示:

12.默認您的規則裏應該是空的,這裏直接點擊上面的加號添加一個規則(符合規則要求的纔會被轉發),點擊右上角的加號圖標,如下圖所示:

13.點擊右上角的加號圖標後,進入過濾規則添加界面,如下圖所示:

(1)在Network id處 選擇當前wifi的SSID

(2)Action 選擇 Local proxy chain

(3)Application 選擇需要強制代理的APP

(4)Hostname 及 Port 不填 表示所有的都會被強制代理,因爲APP可能會使用其他的網絡協議不一定都是http,可能不希望把所有流量都引流到http代理服務器,這個時候就會使用這個配置指定ip及端口才轉發

14.添加好以後,點擊右上角的保存圖標,如下圖所示:

15.點擊“保存”後,跳轉到規則界面,如下圖所示:

16.啓動Drony:返回到SETTING主頁,滑動到LOG頁,點擊下面“OFF”按鈕,

17.點擊“確定”,使其處於ON的狀態(表示啓用),如下圖所示:

4.3開啓代理抓包軟件

宏哥這裏代理抓包軟件使用的是Fiddler。Fiddler的使用這裏不再介紹,需要打開遠程代理,並在手機中安裝Fiddler根證書。這裏宏哥就不做贅述,前邊都有詳細的介紹

經過上面到配置,這些APP的HTTP流量我們就可以通過代理抓包軟件獲取,https流量也可能正常解碼。

5.小結

 宏哥這裏只是提供一種思路供你學習和實踐。 好了,今天時間也不早了,宏哥就講解和分享到這裏,感謝你耐心地閱讀!!!

6.拓展

6.1如何下載google play上的apk安裝包

之前一直沒有從Google Play上下載過apk文件,也不知道怎麼下載,帶來過不便,今天下載查了一下資料,並親自實踐,發現很簡單。

前提:能FQ訪問Google。

共分兩個步驟:

1,訪問Google play

https://play.google.com/store/apps

搜索你想要的應用。

打開應用詳情頁,複製URL地址到步驟2。

2,訪問

https://apps.evozi.com/apk-downloader/

將步驟1中的鏈接粘貼到這個URL中的輸入框,點擊按鈕(藍色)解析出下載apk的鏈接,再點擊下載鏈接(綠色)就下載到你的電腦了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章