Frida证书抓取

极客

Frida证书抓取实战:HTTPS抓包原来这么简单,别再傻傻装证书了!

大家好呀,我是你们的老朋友,一个在逆向和安全测试路上摸爬滚打了好几年的普通技术宅,今天想跟大家聊聊一个特别实用、也特别容易踩坑的话题——Frida证书抓取,哎,说到这个,我猜很多做App安全测试或者爬虫的小伙伴,肯定都遇到过这样的场景:兴致勃勃地打开Burp Suite或者Charles,准备抓个HTTPS包看看接口,结果呢?App直接给你来个“网络连接失败”或者“证书校验不通过”,气得你直拍桌子!😤

Frida证书抓取

其实吧,这事儿真不怪你,现在的App越来越“精明”了,什么SSL Pinning(证书绑定)、双向认证,玩得贼溜,你就算把Burp的CA证书装到系统里,人家App也只认自己内置的那张证书,根本不甩你,那怎么办呢?别急,今天我就手把手带你用Frida证书抓取这个神器,把那些顽固的HTTPS流量统统剥光,让你看得清清楚楚!

为啥传统的抓包方式不灵了?

先啰嗦两句原理哈,懂行的大佬可以直接跳过,以前我们抓HTTPS,无非就是在手机里装个Charles或者Burp的根证书,然后设置代理,但现在的App,尤其是金融、社交类的,基本都会做证书校验,它们要么在代码里硬编码了服务器的证书指纹,要么用OkHttp的CertificatePinner,要么干脆把证书打包在assets里,你一代理,证书链对不上,App直接拒绝连接。

这时候,Frida证书抓取就派上用场了,Frida是个动态插桩框架,说白了就是能让你在App运行的时候,偷偷“劫持”它的函数,改改返回值、打印点东西,我们用它来绕过SSL Pinning,或者直接Hook掉证书校验的函数,让App以为我们的代理证书就是它想要的,是不是听起来就很刺激?😎

Frida证书抓取实战,走起!

好了,不废话,直接上干货,我假设你已经装好了Frida、Python环境,手机也root了(没root的话可以用frida-gadget,但今天先讲root环境,简单点)。

第一步:找到目标App的包名和进程

这个简单,frida-ps -U 一下,看看你要搞的App叫啥,比如咱们就拿一个常见的测试App举例,包名是 com.example.target。

第二步:写一个简单的Hook脚本

咱们的目标是绕过SSL Pinning,对于大多数用OkHttp的App,核心就是CertificatePinner这个类,我们可以直接Hook它的check方法,让它啥也不干。

Java.perform(function() {
    var CertificatePinner = Java.use('okhttp3.CertificatePinner');
    CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(host, peerCertificates) {
        console.log('[+] 绕过SSL Pinning,目标Host: ' + host);
        return; // 直接返回,不抛异常
    };
});

你看,就这么几行,简单吧?但别高兴太早,有些App不止用OkHttp,还用HttpsURLConnection,甚至自己写Native层的校验,这时候就得祭出更狠的招数了。

第三步:Hook系统级的证书校验

咱们可以直接Hook javax.net.ssl.X509TrustManager 的 checkServerTrusted 方法,让所有证书都“可信”,这招几乎通杀所有Java层的证书校验。

Java.perform(function() {
    var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    var TrustManager = Java.registerClass({
        name: 'com.example.TrustManager',
        implements: [X509TrustManager],
        methods: {
            checkClientTrusted: function(chain, authType) {},
            checkServerTrusted: function(chain, authType) {},
            getAcceptedIssuers: function() { return []; }
        }
    });
    // 然后替换掉SSLContext里的TrustManager
    var SSLContext = Java.use('javax.net.ssl.SSLContext');
    SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom').implementation = function(keyManagers, trustManagers, secureRandom) {
        console.log('[+] 替换TrustManager,绕过证书校验');
        this.init(keyManagers, [TrustManager.$new()], secureRandom);
    };
});

哇,这个就有点厉害了,但有时候App会检测你是否用了代理,或者检测Frida本身,这时候就得配合其他反反调试的手段,比如改改ro.debuggable,或者用Magisk Hide,不过今天咱不展开,不然就跑题了。

第四步:跑起来看效果

把脚本保存成 bypass.js,然后运行:

frida -U -f com.example.target -l bypass.js --no-pause

这时候你再打开Burp,设置好代理,去操作App,嘿!你会发现,原本那些“网络错误”全没了,HTTPS请求一个接一个地出现在Burp里,明文看得一清二楚,那种感觉,就像你费了半天劲终于撬开了一把锁,爽!🥳

几个容易踩的坑,我得提醒你

  1. App有Native层的SSL Pinning:比如用了BoringSSL或者自己实现的校验,这时候光Hook Java层没用,得用Frida的Interceptor去Hook SSL_get_verify_result 或者 X509_verify_cert 这些Native函数,这个稍微复杂点,下次我单独开一篇讲。

  2. Frida被检测:有些App会扫描/data/local/tmp下有没有frida-server,或者检测进程名里有没有“frida”,这时候你可以把frida-server改名,或者用非标准端口。

  3. Android 7.0以上用户证书不信任:如果你不想Hook,也可以把Burp的证书装到系统证书目录(需要root),但很多App还是会做Pinning,所以Frida证书抓取还是最稳妥的方案。

最后唠叨几句

说实话,Frida证书抓取这玩意儿,学会了是真的香,不管是做安全测试、爬虫逆向,还是单纯想看看某个App的接口长啥样,它都能帮你省下大把时间,但咱也得记住,技术是把双刃剑,别拿去干坏事哈,不然警察叔叔请喝茶可别怪我没提醒你。😉

好了,今天的分享就到这里,如果你在实操过程中遇到啥问题,或者有更骚的姿势,欢迎在评论区留言,咱们一起交流,觉得有用的话,别忘了点个赞、转发给需要的朋友,下次我打算写写 Frida Native层Hook 的实战,想看的记得关注我哦!拜拜~👋

文章版权声明:除非注明,否则均为极客网安-咸鱼原创文章,转载或复制请以超链接形式并注明出处。

目录[+]