首页
社区
课程
招聘
[原创] Frida解决证书绑定问题
2024-1-4 11:38 9449

[原创] Frida解决证书绑定问题

2024-1-4 11:38
9449

Frida解决证书绑定问题

客户端校验服务端--SSL Pinning

案例链接

1
链接: https://pan.baidu.com/s/1xKT-zK1TEdTTV7cgLMW6RQ?pwd=3597 提取码: 3597

1)在确定代理成功,能正常抓取https流量后,打开APP,这里以dida.apk​为例。打开案例APP并测试通过手机号注册发送验证码流程,在单机发送验证码​按钮后会提示发送失败,请重试

image

2)观察数据包发现提示Client closed the connection before a request was made. Possibly the SSL certificate was rejected.​ 判断出是客户端主动停止与服务器端的连接,APP使用了证书绑定技术

image

3)解决方案是使证书绑定的函数失效,需要对不同网络框架中证书绑定的相关代码有一定了解。例如,App使用okhttp3网络框架进行证书绑定(见代码清单10-1),那么最终使用的证书绑定类总是CertificatePinner类,此时Hook的目标就是CertificatePinner类中的函数;App使用TrustManager完成证书的绑定,那么Hook的目标就是TrustManager类中的证书绑定的函数。

OkHttp3证书绑定代码

image

由于网络框架有很多,没对每个网络框架进行函数确定工作量会很大。幸运的是前人已经完成了很多种网络框架的证书绑定函数的收集工作并将这些函数的Hook集成到Objection或其他工具中。这里介绍两种工具,已经涵盖了绝大多数的网络框架

  • Objection
  • github上一个项目(DroidSSLUnpinning)

https://github.com/WooyunDota/DroidSSLUnpinning/blob/master/ObjectionUnpinningPlus/hooks.js

objection 例子:

1)考虑到App可能在启动时就已经完成了证书绑定,在adbshell中先使用kill命令将App完全关闭再使用Objection进行注入,并使用如下命令完成证书解绑。

以下命令需要在Objection注入时执行,因此还需要使用Objection的-s/--start-command参数达到命令在应用启动之前就执行的效果。

image

2)在objection完成Hook后,同样继续测试发送验证码接口,发现仍然提示发送失败,请重试​ 。可能是objection工具并未集成足够多的网络框架证书绑定函数,可尝试使用上面推荐的 DroidSSLUnpinning​ 项目,该项目集成了更多的网络框架证书绑定相关函数。

手工Hook

经过DroidSSLUnpinning​和objection等将近20个网络框架证书绑定函数的Hook都失效的情况下,差不多可以得到结论:APP被混淆了。应对这种情况,大致有两个方法:

  • 使用objection对所有HTTP字符串相关类进行Hook
  • 考虑到App在验证证书时一定会打开证书文件判断是否是App自身信任的框架,因此一定会使用File类的构造函数打开证书文件获得文件句柄,在测试时可以使用Objection Hook上所有File类的构造函数,即File.$init函数。(推荐)

1)使用Hook File类句柄方法,需要注意的是,在终端中“是特殊符号,因此在输入时需要对字符进行转义。可以参考的Objection注入命令:

1
objection -g cn.ticktick.task explore -s "android hooking watch class_method java.io.File.\$init --dump-args --dump-backtrace --dump-return"

然后点击发送验证码​ 在打印日志中以/system/etc/security/cacerts这个系统存放证书的路径为关键词在终端进行搜索,最终会发现有一个栈信息中存在着非常明显的CertificatePinner.java 文 件 名 信 息 , 因 此 可 以 判 定 对 应 的 函 数xp.f.a()就是对应的完成证书绑定的函数。

image​​

2)由于objection不支持对函数逻辑进行修改,故使用Frida脚本进行Hook

function killCertificatePinner(){
    Java.perform(function(){
        console.log("Beginning killCertificatePinner !...")
        Java.use("xp.f").a.implementation = function(str, list){
            console.log("called xp.f.a ~")
            // 将函数返回值置空
            return ;
        }
    })
}

function main(){
    killCertificatePinner();
}

setImmediate(main)

3)在使用Frida脚本Hook后,再次对相关流程进行测试的抓包结果如下所示

image​​

image

Frida脚本绕过服务器端校验客户端证书

本案例使用便利蜂APP(bianlifeng.apk),也可以网上下载

1)使用浏览器访问百度测试,确定Charles可以正常抓取手机端流量,然后设置代理,打开便利蜂APP,点击登录或注册,输入手机号,获取验证码,发现获取失败,查看数据包返回 400 No required SSL certificate was sent​ ,可以得知该APP使用了服务端校验证书的方式

image

2)从安全客上下载Frida脚本,以spawn运行脚本,即可打印出证书名称和密码

实用FRIDA进阶:内存漫游、hook anywhere、抓包

脚本代码

function hook_KeyStore_load() {
    Java.perform(function () {
        var StringClass = Java.use("java.lang.String");
        var KeyStore = Java.use("java.security.KeyStore");
        KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {
            // printStack("KeyStore.load1");
            // 输出调用栈
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
            console.log("KeyStore.load1:", arg0);
            this.load(arg0);
        };
        KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {
            // printStack("KeyStore.load2");
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
            console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);
            this.load(arg0, arg1);
        };

        console.log("hook_KeyStore_load...");
    });
}

hook_KeyStore_load()
1
frida -U -f com.bianlifeng.customer.android -l ./agent/Chap10/hookKeyStore.js --no-pause

运行结果:

image

获取证书名称,密码及其他信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
KeyStore.load1: null
java.lang.Throwable
        at java.security.KeyStore.load(Native Method)
        at com.wormpex.sdk.errors.CrashHandler.getKeyStore(Native Method)
        at com.wormpex.sdk.network.a.c(ClientAuthenticationSocketFactory.java:2)
        at com.wormpex.sdk.network.a.d(ClientAuthenticationSocketFactory.java:3)
        at com.wormpex.sdk.network.a.b(ClientAuthenticationSocketFactory.java:1)
        at com.wormpex.h.f$b$a.call(SdkInitHelper.java:2)
        at com.wormpex.h.f$b$a.call(SdkInitHelper.java:1)
        at com.wormpex.sdk.network.LazySSLSocketFactory.ensureCreateDelegate(LazySSLSocketFactory.java:8)
        at com.wormpex.sdk.network.LazySSLSocketFactory.preCreateDelegate(LazySSLSocketFactory.java:1)
        at com.wormpex.h.f$b$b$a.run(SdkInitHelper.java:1)
        at com.wormpex.j.c.a$a.queueIdle(QUtil.java:3)
        at android.os.MessageQueue.next(MessageQueue.java:404)
        at android.os.Looper.loop(Looper.java:193)
        at android.os.HandlerThread.run(HandlerThread.java:67)
 
KeyStore.load2: java.io.ByteArrayInputStream@bced593 blibee


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 9
打赏
分享
最新回复 (11)
雪    币: 21012
活跃值: (30261)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2024-1-4 13:41
2
1
感谢分享
雪    币: 80
活跃值: (2749)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
calleng 2024-1-4 14:07
3
0
老,真强,都上实战嘞
雪    币: 1489
活跃值: (2011)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huluxia 2024-1-4 14:18
4
0
感谢分享,都是干货
雪    币: 5418
活跃值: (4243)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_rjdrqvpa 2024-1-4 15:29
5
0

滴答app无法复现文章内容,文章给的链接里面的是5.8.6.0版本。


使用Objection对file构造函数hook,堆栈里面没有CertificatePinner.java,即堆栈信息对不上;

文章通过堆栈信息CertificatePinner.java定位到函数xp.f.a()就是对应的完成证书绑定的函数,然后通过hook将函数体清空,实现过sslpinning。

我先通过枚举classloader,来遍历xp.f这个类,没找到;


然后,我反编译app,发现这个版本确实没有类xp.f


综上,楼主可能需要更新一下文章


雪    币: 1002
活跃值: (1533)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
WMBa0 2024-1-4 15:36
6
0
十分感谢!
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_ldbucrik 2024-1-4 18:27
7
0
感谢分享
雪    币: 65
活跃值: (1128)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
龙游天下178 2024-1-8 22:10
8
0
无法复现
雪    币: 1180
活跃值: (214722)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
shinratensei 1 2024-1-9 09:54
9
0
tql
雪    币: 1982
活跃值: (1308)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
南枫 2024-1-9 10:13
10
0
mark
雪    币: 1598
活跃值: (1443)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
混迹 2024-1-10 22:47
11
0
感谢分享~
雪    币: 3862
活跃值: (1294)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
braintrust 2024-1-16 22:45
12
0
z1.g.a 这个类
游客
登录 | 注册 方可回帖
返回