强混淆APP SSLPinning Bypass
2023-1-13 08:44:56 Author: 白帽子(查看原文) 阅读量:28 收藏

前言

遇见App存在证书绑定时,一般会采用工具一把梭,比较熟悉的有justrustme模块;以及使用objection将SSLpinning给disable掉;还有就是某些大佬自己集成的十多种绕过证书绑定的框架如DroidSSLUnpinning、FridaContainer。使用这些工具基本上可以绕过90%以上的证书绑定,但有些APP做了混淆后上面这些工具就失效了,通过学习肉师傅传授的思路,可实现混淆APP SSLPinning Bypass。

正文

首先从开发角度来了解证书绑定如何实现,从下面代码中可以看出针对该网址www.tetsukay.app从系统里取出文件,取出文件之后计算sha256,然后与该值YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=进行比对。

fun withValidCAPinner(): Unit = runBlocking {
    val job = GlobalScope.launch {
        val request = Request.Builder().url("https://www.tetsukay.app/").build()
        val pinner = CertificatePinner.Builder()
                .add("www.tetsukay.app""sha256/YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=")
                .build()
        val client = OkHttpClient.Builder().certificatePinner(pinner).build()
        client.newCall(request).execute().isSuccessful.should be true
    }
    job.join()
    return@runBlocking
}

所以我们可以从框架层的两个地方进行分析

1、取出文件

2、计算sha256

打开文件时,hook构造函数java.io.File,然后从构造函数的重载中发现java.lang.String会被反复调用进行打开证书文件。

通过分析得出,打开的文件中包含该cacert证书的路径,然后调用栈中包含该函数

X509TrustManagerExtensions.checkServerTrusted

满足这两个条件,把消息和调用栈传出去,也就定位到哪个函数执行了ssl证书绑定。

Java.use("java.io.File").$init.overload('java.io.File''java.lang.String').implementation = function (file, cert) {
      var result = this.$init(file, cert)
      var stack = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new());
      if (file.getPath().indexOf("cacert") >= 0 && stack.indexOf("X509TrustManagerExtensions.checkServerTrusted") >= 0) {
        var message = {};
        message["function"] = "SSLpinning position locator" + file.getPath() + " " + cert;
        message["stack"] = stack;
        var data = Memory.alloc(1);
        send(message, Memory.readByteArray(data, 1))
      }
      return result;
    }

我们运行该脚本后在APP登录处输入账号密码,然后在保存生成的文件中搜索SSLpinning,可以很明显的发现该混淆后的类z1.g.a(CertificatePinner.java:13)。

python r0capture.py -U -f cn.xxx.xxx -v >>xxx.txt


当然也可以搜索

X509TrustManagerExtensions.checkServerTrusted

同样也能定位到该混淆后的类。

找出该类后,我们的做法就是hook该类,将.a返回值置空,以此达到校验失效的目的来实现绕过。

setImmediate(function(){
    Java.perform(function(){
        console.log("Bypassing")
        Java.use("z1.g").a.implementation = function(){
            console.log("called here")
            return;
        }
    })
})

编写好hook代码,使用frida加载绕过。

frida -U -f cn.xxx.xxx -l bypassPinning.js --no-pause

结果展示,如下

参考链接:

https://www.anquanke.com/post/id/197657https://zhuanlan.zhihu.com/p/58204817https://qiita.com/tetsukay/items/ad6cf55c740a57050cd3

E

N

D

Tide安全团队正式成立于2019年1月,是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、系统安全、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。

团队作为“省级等保关键技术实验室”先后与哈工大、齐鲁银行、聊城大学、交通学院等多个高校名企建立联合技术实验室,近三年来在网络安全技术方面开展研发项目60余项,获得各类自主知识产权30余项,省市级科技项目立项20余项,研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。对安全感兴趣的小伙伴可以加入或关注我们。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650246454&idx=2&sn=2a97532778cc9adcaa78724f511ff595&chksm=82ea569fb59ddf89c68911b787653b5f0aae8afb7bac8feedd23eb5e791ccae48e7e95b0c494#rd
如有侵权请联系:admin#unsafe.sh