【Android 抓包对抗】客户端证书和域名校验绕过

android,对抗,客户端,证书,域名,校验,绕过 · 浏览次数 : 100

小编点评

**抓包步骤:** 1. 使用 `OkHttp` 构造一个 `OkHttpClient`。 2. 在 `OkHttpClient` 中设置 `sslSocketFactory`,指定 `SSLContext` 中的 `TrustManager`。 3. 设置 `hostnameVerifier`,指定要验证的域名。 4. 使用 `OkHttp` 建立 SSL 连接并获取证书。 5. 检查证书是否已验证,以及是否符合指定的域名。 **绕过问题:** 1. 在 `SSL Proxy Settings` 中设置 `host` 和 `port`。 2. 将设置的值设置为 `*:443` 和 `*:10081`。 **完整代码:** ```java import com.dta.dtawallpaper.util.OkHttpUtil; public class Main { public static void main(String[] args) { // TrustAllManager var TrustAllManagerClass = Java.registerClass({ name: "TrustAllManager", implements:[Java.use("javax.net.ssl.X509TrustManager")] }); // MyHostnameVerify var MyHostnameVerify = Java.registerClass({ name: "MyHostnameVerify", implements:[Java.use("javax.net.ssl.HostnameVerifier")] }); // 创建 OkHttpClient OkHttpClient okHttpClient = new OkHttpClient.Builder() .sslSocketFactory(new SSLSocketFactory() { @Override public void setDefaultPort(int port) { System.setProperty("javax.net.ssl.SSLSocketFactory.port", port + ""); } }) .hostnameVerifier(MyHostnameVerify.getClass()) .build(); // 执行请求 try { Certificate certificate = CertificateFactory.getInstance("X509").generateCertificate(OkHttpUtil.loadCertificate("wallpaper.cer")); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("wallpaper", certificate); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustManagers, null); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); return okHttpClient.newSession().connect(null, certificate.getEncodedSubject()); } catch (Exception e) { e.printStackTrace(); } } } ```

正文

1. 按照之前的方式(https://www.cnblogs.com/gradyblog/p/17197707.html)进行抓包发现证书校验失败

SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown)

2. apk拖入到jadx中查看

private static OkHttpClient getClient() {
        OkHttpClient okHttpClient = client;
        if (okHttpClient == null) {
            try {
                Certificate generateCertificate = CertificateFactory.getInstance("X509").generateCertificate(in_cer);
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null, null);
                keyStore.setCertificateEntry("wallpaper", generateCertificate);
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
                TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
                SSLContext sSLContext = SSLContext.getInstance("TLS");
                sSLContext.init(null, trustManagers, null);
                SSLSocketFactory socketFactory = sSLContext.getSocketFactory();
                OkHttpClient.Builder builder = new OkHttpClient.Builder();
                builder.sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]);
                builder.hostnameVerifier(new HostnameVerifier() { // from class: com.dta.dtawallpaper.util.OkHttpUtil.1
                    @Override // javax.net.ssl.HostnameVerifier
                    public boolean verify(String str, SSLSession sSLSession) {
                        return str.equals("www.dtasecurity.cn");
                    }
                });
......
                return builder.build();
            } catch (Exception unused) {
                return null;
            }
        }
        return okHttpClient;
    }

从这里可以看出进行了 客户端证书的校验,和Hostname的校验,就防止了中间人转发的问题,但这也不是问题

2. 编写frida脚本绕过

function main(){
    Java.perform(function (){
 
        //TrustAllManager
        var TrustAllManagerClass = Java.registerClass({
            name: "TrustAllManager",
            implements:[Java.use("javax.net.ssl.X509TrustManager")],
            methods: {
                checkClientTrusted(chain, authType) {
                    console.log("checkClientTrusted Called!!")
                },
                checkServerTrusted(chain, authType) {
                    console.log("checkServerTrusted Called!!")
                },
                getAcceptedIssuers() {
                  return [];
                },
              }
        })
        var trustAllManagerHandle = TrustAllManagerClass.$new()
 
        var sslContext = Java.use("javax.net.ssl.SSLContext").getInstance("TLS")
        var trustManagers = Java.array("Ljavax.net.ssl.X509TrustManager;",[trustAllManagerHandle])
        sslContext.init(null,trustManagers,null)
        var sslSocketFactory = sslContext.getSocketFactory()
 
        Java.use("okhttp3.OkHttpClient$Builder").sslSocketFactory.overload('javax.net.ssl.SSLSocketFactory', 'javax.net.ssl.X509TrustManager').implementation = function(arg0, arg1){
            console.log("sslSocketFactory Called!!")
            return this.sslSocketFactory(sslSocketFactory,trustAllManagerHandle)
        }
 
 
        //HostnameVerify
        var MyHostnameVerify = Java.registerClass({
            name: "MyHostnameVerify",
            implements:[Java.use("javax.net.ssl.HostnameVerifier")],
            methods: {
                verify(hostname, session){
                    console.log(hostname)
                    return true
                }
            }
        })
        var myHostnameVerifyHandle = MyHostnameVerify.$new()
 
        Java.use("okhttp3.OkHttpClient$Builder").build.implementation = function(){
            this.hostnameVerifier(myHostnameVerifyHandle)
            console.log(this.hostnameVerifier)
            return this.build()
        }
    })
}
 
setImmediate(main)


这里主要是自定义了TrustAllManager类和HostnameVerifier类,来控制其行为实现绕过

3. 以spawn模式执行,成功抓到https的包

ps 这里遇到了一个小问题,但是本应该不存在的 首先我们要在 (SSL Proxy Settings)中设置好host和port ,比如我设置的是*:443 和 *:10081,但是有一个请求还是没有显示,右键它 选择enable ssl proxying就好了
参考: https://stackoverflow.com/questions/49117151/charles-proxy-ssl-ssl-proxying-not-enabled-for-this-host

与【Android 抓包对抗】客户端证书和域名校验绕过相似的内容:

【Android 抓包对抗】客户端证书和域名校验绕过

1. 按照之前的方式(https://www.cnblogs.com/gradyblog/p/17197707.html)进行抓包发现证书校验失败 SSL handshake with client failed: An unknown issue occurred processing the c

【Android 抓包对抗】代理检查绕过

1. 安装apk,点进去发现一点就挂 2. apk 拖入到jadx中观察,发现多出检查,一旦满足条件就会退出 .... if (((ConnectivityManager) getSystemService("connectivity")).getNetworkInfo(17).isConnecte

《吐血整理》高级系列教程-吃透Fiddler抓包教程(35)-Fiddler如何抓取微信小程序的包-下篇

1.简介 通过前边和宏哥的学习,我们了解到Android 7.0 之后增加了对第三方证书的限制,抓包工具(charles、fiddler等)提供的证书都无法通过校验,也就无法抓取HTTPS请求了,对测试工作影响很大。 最近更新的微信 7.0 也增加了第三方证书校验,导致无法正常抓包。 2.解决思路

《吐血整理》高级系列教程-吃透Fiddler抓包教程(32)-Fiddler如何抓取IOS系统中Flutter应用程序的包

1.简介 上一篇讲解了安卓手机可以通过VPN代理来抓取Flutter应用程序的包,iOS(iphone)同样使用上一篇中VPN方法(原理与android是一致的),同样需要使用到VPN,在iOS也有许多与drony功能类似的软件,大家可以自己选择自己喜欢的使用,宏哥这里使用的是Shadowrocke

《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(6)-Charles安卓手机抓包大揭秘

1.简介 Charles和Fiddler一样不但能截获各种浏览器发出的 HTTP 请求,也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Charles也能截获 Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。 今天宏哥讲解和分享Charles如何

使用 shell 脚本自动申请进京证 (六环外) —— debug 过程

写好的自动办理六环外进京证脚本跑不通,总是返回办理业务人数较多 (500) 错误,Charles / VNET 抓包、android 交叉编译 jq、升级 curl…都不起作用,最终还是神奇的 adb shell 帮了大忙,最后定位到根因,居然是用 shell 字符串长度作为数据长度导致的,这错误犯的有点低级……

《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(16)-Charles其他骚操作之大结局

1.简介 今天就说一些Charles的其他操作、以及抓包跨域的问题和常见的问题如何解决。到此Charles这一系列的文章也要和大家说再见了,其他什么小程序、Android7.0等等的问题可以查看宏哥的Fiddler系列文章,只不过是将Fiddler换成Charles而已。 2.模拟403/404 其

Unity 利用Cache实现边下边玩

现在手机游戏的常规更新方案都是在启动时下载所有资源更新,游戏质量高的、用户粘性大的有底气,先安装2个G,启动再更新2个G,文件小了玩家还觉得品质不行不想玩。 最近在做微信、抖音小游戏,使用他们提供的资源缓存方案,现在要转成Android APP, 也想用这种边下边玩的机制把首包做小。 其实很简单,直

一个 .NET 开源的地图组件库 - Mapsui

前言 今天大姚给大家分享一个.NET开源(MIT License)、免费、同时支持多平台框架(MAUI、WPF、Avalonia、Uno、Blazor、WinUI、Eto、.NET Android 和 .NET iOS)地图组件库:Mapsui。 项目源代码 支持的UI框架的NuGet包 创建Bla

【Android 逆向】VM Kali 中 charles 抓android https 协议

1. 虚拟机调成桥接模式(不用选择 复制物理网络链接状态) 2. 虚拟机中 打开 Charles 4. 选择 Proxy ->SSL Proxying Settings 1. 选择SSL Proxying 菜单 2. 勾选Enable SSL Proxying 3. 在include 中选择Add