前言
當年還在學校的時候,就接觸到了抓包,當時還在貼吧寫了一篇小白文來誤導小白(不是。但當時的自己還沒接觸到逆向,竟然對抓包沒有提起興趣,說到底又是太年輕,不懂事。時至今日,才發現它是安全人員必須要掌握的基本技能,面試安全崗位也多多少會問到與抓包相關的知識。抓包(packet capture)是查看數據包發送和接收過程的手段。抓包也有很多種辦法,可以在軟件層面對函數進行hook,查看發送或接受的數據包,還有利用WireShark,tcpdump,Fiddler,Charles等第三方工具來抓包。本文演示如何利用Charles來對AndroidApp進行抓包,並且強行讓App走代理
工具准備
步驟
安裝Charles后打開。依次選擇菜單Proxy -> SSL Proxying Settings...
在SSL Proxying標簽下勾選Enable SSL Proxying,再點擊Add按鈕
添加一條Host為*
,Port為443
的規則,如圖:
點擊OK
依次點擊Help -> SSL Proxying -> Save Charles Root Certificate...導出根證書,另存為charles.pem
將下載好的OpenSSL放入環境變量
轉到證書導出目錄,打開命令行,執行以下命令:
openssl x509 -subject_hash_old -in charles.pem
根據輸出的內容,將charles.pem重命名為b6a3624b.0
,注意文件后綴是0
然后重新掛載手機的system分區
adb root
adb remount
將重命名后的文件推入/system/etc/security/cacerts目錄中
adb push b6a3624b.0 /system/etc/security/cacerts
回到Charles,依次選擇Proxy->Proxy Settings
設置一個端口,按確定
在手機WIFI設置頁面,給連接的WIFI設置代理,代理到Charles。代理服務器主機名寫電腦的主機名或者ip地址,代理服務器端口寫上面在Charles中設置的端口,寫完后點保存
接下來,手機的https包都會被轉到Chales中,並成功解析
當然,有時候事情不會那么順利。咱們抓包,那別人也會想辦法防止抓包。如果抓包的時候我們知道應用明明有http請求但是在抓包工具中卻抓不到包,那么應用中很有可能設置了不讓請求走代理,常用的設置代碼如下:
- URLConnection類
public static String get(String urlStr){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
InputStream inputStream = null;
try {
URL url = new URL(urlStr);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
httpURLConnection.setRequestMethod("GET");
inputStream = httpURLConnection.getInputStream();
if(httpURLConnection.getResponseCode() == 200) {
byte[] buf = new byte[1024];
int len = -1;
while ((len = inputStream.read(buf)) != -1) {
byteArrayOutputStream.write(buf, 0, len);
}
}
}
catch (Exception e){
return e.toString();
}
finally {
close(inputStream);
close(byteArrayOutputStream);
}
return byteArrayOutputStream.toString();
}
注意上面的openConnection(Proxy.NO_PROXY)
,這就是設置請求不走代理的地方
- OkHttp庫
public static String get(String url) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
// //方式一:
// client.proxy(Proxy.NO_PROXY);
// //方式二:
ProxySelector proxySelector = new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
return null;
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
}
};
client.proxySelector(proxySelector);
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.build().newCall(request).execute()) {
return response.body().string();
}
catch (Exception e){
return e.toString();
}
}
同樣的,上面注釋標出的地方也是設置請求不走代理
針對這些我們可以利用Hook相應的方法強行讓http請求走代理,這里使用frida來進行hook,代碼如下:
if(Java.available){
Java.perform(function(){
//openConnection
var URL = Java.use("java.net.URL")
var openConnection1 = URL.openConnection.overload("java.net.Proxy")
var openConnection2 = URL.openConnection.overload()
openConnection1.implementation = function(proxy){
console.log("openConnection() proxy = " + proxy)
return openConnection2.call(this)
}
//okhttp
var OkHttpClientBuilder = Java.use("okhttp3.OkHttpClient$Builder")
var proxy = OkHttpClientBuilder.proxy.overload("java.net.Proxy")
proxy.implementation = function(proxy){
console.log("proxy() prxoy = " + proxy)
return null
}
var proxySelector = OkHttpClientBuilder.proxySelector.overload("java.net.ProxySelector")
proxySelector.implementation = function(proxySelector){
console.log("proxySelector() proxySelector = " + proxySelector)
return null
}
})
}