博客 / 詳情

返回

Android安卓進階之——一文帶你瞭解抓包和反抓包

今天主要跟大家介紹一下Android的抓包和防止抓包

介紹兩款抓包工具,Profiter和Charles。

工具環境:

Android Studio 4.2.2

手機Google Pixel 3XL Android 11

使用Profiler 工具抓包

將自己的手機連接到電腦上,然後打開Android Studio 的Profiler

Android Studio 白狐及以下版本的NetWork Inspector 在 Profler 中,大黃蜂版本的NetWork Inspector 在 App Inspection中。

然後app 訪問網絡會有這樣提示:

我們選中波動 ,可以看到請求的信息:

然後我們點擊接口信息之後,可以看到請求的詳細信息:

這樣我們就可以通過AndroidStudio的Profiler 輕鬆地抓取我們App 的網絡信息了。

使用Charles 工具抓包

1.安裝證書

首先下載Charles ,打開之後點擊Help->SSL Proxying -> Install Charles Root Certificate 安裝根證書

然後雙擊證書,進行信任

電腦端這就配置完了, 接下來配置 客户端

方式1:

手機端通過瀏覽器下載證書。

手機端 對連接wifi 進行代理設置,設置手動代理,將charles 提示的代理地址 設置好,然後charles 就會有一個提示:

然後我們同意就好了。

然後瀏覽器輸入chls.pro/ssl 進行下載證書,下載完成進行安裝即可;不過有時候這種方式無法安裝,可以通過方式2進行安裝。

方式2:

通過Help->SSL Proxying -> Save Charles Root Certificate 將證書保存在電腦上

然後上傳到手機端,點擊設置-安全-加密與憑證-安裝證書-CA證書,選擇我們剛剛的證書進行安裝即可。

至此,安裝證書的步驟我們就完成了。

2.抓包

此時,當我們進行網絡訪問 的時候,可以在charles上面看到我們訪問的數據了

我們可以通過左下角的Filter 進行地址過濾,找到我們想看的網絡數據。

防止抓包

前面講到,默認的 Android Https 配置下,只要使用 Android7.0 以下的手機、或者找個 Root 設備安裝把用户證書(比如charles證書)想辦法搞進系統證書那部分,就可以抓包了。這對於黑產來説也忒忒忒簡單了。那麼怎麼防止呢?

答案是配置你信任的網站證書或者配置信任的認證鏈。

**1.Android 官方配置信息證書
(聲明:這種方法只能防篡改設備的根證書,防不了使用 Android7.0 以下的手機。)**

比如你可以像這樣把你信任的網站的證書給搞下來

步驟①:點擊域名旁邊鎖的圖標,彈出框裏面點「證書」

mac系統,對着證書那個圖標拖動到某個文件夾裏。這樣你就能得到一個HTTPS的裏面的SSL裏面的非對稱加密算法的公鑰。

步驟②:放進 res/raw 文件夾裏,在network_security_config.xml 裏寫上相關配置

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>

    <!-- 這個是全局的基礎的配置 -->
    <base-config>
        <trust-anchors>
            <!-- 如果整個base-config都不寫,就等於是<certificates src="system" /> -->
            <!-- 這裏寫全局基礎配置,只信任下面某幾個證書 -->
            <certificates src="@raw/zhihu" />
            <certificates src="@raw/baidu" />
        </trust-anchors>
    </base-config>

    <!-- 如果只對某些涉及數據安全的私密域名進行保護,可以針對某個域名,只信任某幾個證書 -->
    <domain-config>
        <domain includeSubdomains="true">zhihu.com</domain>
        <trust-anchors>
            <certificates src="@raw/zhihu" />
            <certificates src="@raw/tencent" />
        </trust-anchors>
    </domain-config>

    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>

</network-security-config>

以上就是 Android 官方推薦的做法。

——————————————— 分割線 ———————————————

**2. OkHttp 配置信任認證鏈
(聲明:這種方法是全方面防禦,在 Android7.0 以下設備也能起作用)**

步驟①:寫一個 CertificatePinner 的配置

其中的 add方法兩個參數。第一個參數是網址的域名host,第二個是sha256的證書。證書我們目前不清楚,先輸入這麼一段字符串。使用這麼一段錯誤的配置運行後將會報錯,然後在日誌裏得到正確的配置信息。

注意第一個參數不要包含協議,也不要省略部分域名,錯誤示例 「https://news-at.zhihu.com」、「zhihu.com」。
第二個參數是個假證書識別串,但是有效的,我測試時候亂輸入了一串「sha256/wrong」沒有觸發到搜想要的結果。
public class ZhihuHttp {

    public static final String ZHIHU_BASE_URL = "https://news-at.zhihu.com/api/";
    private static final ZhihuHttp zhihuHttp = new ZhihuHttp();
    private OkHttpClient okHttpClient;

    private ZhihuHttp() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(10, TimeUnit.SECONDS);
        // 只信任網站對應的證書
        CertificatePinner certificatePinner = new CertificatePinner.Builder()
                .add("news-at.zhihu.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
                .build();
        builder.certificatePinner(certificatePinner);
        okHttpClient = builder.build();
    }
    public static ZhihuHttp getZhihuHttp() {
        return zhihuHttp;
    }
    public void getDailiesWithCallback() {
        Request request = new Request.Builder()
                .url(ZHIHU_BASE_URL + "4/news/latest")
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.e("YAO", "ZhihuHttp.java - onFailure() ----- e:" + e.toString());
                e.printStackTrace();
            }
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Log.e("YAO", "ZhihuHttp.java - onResponse() ----- :" + response.toString());
            }
        });
    }
}

步驟②:執行代碼後報錯。搜索關鍵字,我們能得到這麼一串報錯

Subscriber onError() : javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
  Peer certificate chain:
    sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
    sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=: CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
    sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=: CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
  Pinned certificates for news-at.zhihu.com:
    sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

這報錯的意思是。現在訪問這個鏈接的認證鏈是 Peer certificate chain 下面的3個sha256。

「sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=」
「sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=」
「sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=」
鏈的含義是,第一個sha256對應的證書由第二個sha256對應的證書認證,第二個sha256對應的證書又第三個sha256對應的證書認證。

在代碼裏配置的用於「news-at.zhihu.com」域名的認證 sha256 期望是
「sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=」

因為兩者對應不上,所以請求失敗。然而通過這個方法,我們得到正確的sha256,下面就拿這幾個正確的sha256來配置。

步驟③:配置正確 sha256

CertificatePinner certificatePinner = new CertificatePinner.Builder()
        //正常請求下的證書驗證鏈路
        .add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
        .add("news-at.zhihu.com", "sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=")//CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
        .add("news-at.zhihu.com", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")//CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
        .build();

配置後,這個域名的請求就不能被抓包了。因為開啓抓包後,根證書是 charles 的公鑰,跟期望的 sha256 匹配不上。
一個很重要的點是,其實我們可以不用把3個 sha256 都加上。匹配邏輯是任意一個 sha256 匹配上請求就可以通過了。所以其實可以這麼寫。

CertificatePinner certificatePinner = new CertificatePinner.Builder()
        //正常請求下的證書驗證鏈路
        .add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
        .build();
域名hostname 支持通配符,可以參考OkHttp CertificatePinner部分

驗證結果
按照 OkHttp 官方指導配置完後,使用 charles 抓包看看還能不能在 Android 7.0 以下系統抓到包。
驗證結果,不能抓包,會出現一個報錯:

Subscriber onError() : javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
  Peer certificate chain:
    sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
    sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=: C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (2 十月 2017\, YaodeMacBook-Pro.local)
  Pinned certificates for news-at.zhihu.com:
    sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=
    sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=
    sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=

可以看到現在訪問這個鏈接的認證鏈是 Peer certificate chain 下面的兩個sha256。
「sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=」
「sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=」
報錯的信息裏,第二個 sha256 冒號後面,顯示這串字符來自我的 charles 公鑰。

對比 未使用 和 使用 抓包的報錯信息,發現第一個 sha256 都是來自於知乎的公鑰,但兩個的 sha256 是不一樣的。

//未開啓抓包
sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
//開啓抓包
sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=: CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN

一開始我一直以為這一串東西是SSL公鑰進行一次hash算法得到的字符串。後面觀察後發現不是。
這是兩個公鑰在不同 「中間證書認證」-「中間證書認證」……「根證書認證」這種認證體系下的一個hash串。

所以如果開啓抓包,那麼他對應的根證書是 charles 的公鑰,得出的第一個來自知乎證書的 sha256 就會有所不同。

warning: 配置信任某個具體證書一定要與服務器開發或運維溝通好,因為如果服務器進行了證書替換而App沒有更新到最新證書,App的請求將會失效。如果開啓的是全部域名的證書配置,意味着你連應用內升級或者熱更新都用不了,絕對是重大事故。

還有什麼騷操作

上面講到我們配置到工程代碼裏的是 網站的公鑰(任何人都可以隨意下載)

根據HTTPS的原理,公鑰和私鑰的原理,其實完全可以在代碼裏配置上開發者的 charles 公鑰(只針對某台具體的筆記本,charles 為它生成的一對公鑰私鑰)。因為沒人能根據公鑰能破解出對應的私鑰。
所以如果在在 app 裏配上我們某部電腦 charles 公鑰,以後就可以用那個電腦抓正式環境正式域名的請求了。比如工程加上公司的公用開發機的 charles 公鑰,或者核心App測試大佬的 charles 公鑰。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>

    <!-- 這個是全局的基礎的配置 -->
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <!-- 如果整個base-config都不寫,就等於是<certificates src="system" /> -->
            <!-- 這裏寫全局基礎配置,只信任下面某幾個證書 -->
            <certificates src="@raw/zhihu" />
            <certificates src="@raw/yao_charles" />
        </trust-anchors>
    </base-config>

    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>

</network-security-config>

使用OkHttp的配置的方法,這麼寫:

// 只信任網站對應的證書
CertificatePinner certificatePinner = new CertificatePinner.Builder()
        //正常請求下的證書驗證鏈路
        .add("news-at.zhihu.com", "sha256/f5fNYvDJUKFsO51UowKkyKAlWXZXpaGK6Bah4yX9zmI=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
        .add("news-at.zhihu.com", "sha256/zUIraRNo+4JoAYA7ROeWjARtIoN4rIEbCpfCRQT6N6A=")//CN=GeoTrust RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
        .add("news-at.zhihu.com", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=")//CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US

        //charles 抓包下的配置
        .add("news-at.zhihu.com", "sha256/dVUJFtUhQtJki5t0/j+hMYzTgtVkETqjsogUuyquPPo=")//CN=*.zhihu.com,OU=IT,O=智者四海(北京)技術有限公司,L=北京市,C=CN
        .add("news-at.zhihu.com", "sha256/54ZQa+M6vq6DhdR7DLkc1X6fWmVEZ6wLZaaYwoR4Uvw=")//C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (2 十月 2017\, YaodeMacBook-Pro.local)
        .build();
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.