Bypass ffmpeg的ssl certificate check

0x00 背景

最近在做一个项目,我想使用burp截获ffmpeg发送的请求,但是发现即使我在客户端上装上了burp的CA证书,也还是会出现ssl handshake error。于是我将ffmpeg进行了一下bianry patch,disable了ffmpeg的证书检证。在0x01中我将介绍如何patch,在0x02中我将分析一下为何在客户端上安装了burp的CA证书还是会出现ssl握手错误。

0x01 Bypass

ffmpeg有个功能是从给定的url下载多媒体文件,当url是https,且ffmpeg链接了openssl时,最终会调用tls_open这个函数中来打开url。注意在这个函数中会检查服务器证书:
https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/tls_openssl.c#L262
所以如果想要绕过证明书检测,在libavformat.so中把第二个参数改为0即可:

patch前:

.text:4AEF6DC8 05 00 A0 E1 MOV R0, R5
.text:4AEF6DCC 03 10 A0 E3 MOV R1, #3
.text:4AEF6DD0 00 20 A0 E3 MOV R2, #0
.text:4AEF6DD4 9C B1 FB EB BL SSL_CTX_set_verify 

patch後:

.text:4AEF6DC8 05 00 A0 E1 MOV R0, R5
.text:4AEF6DCC 00 10 A0 E3 MOV R1, #0
.text:4AEF6DD0 00 20 A0 E3 MOV R2, #0
.text:4AEF6DD4 9C B1 FB EB BL SSL_CTX_set_verify 

因为SSL_CTX_set_verify这个函数在libavformat中只用到过一次,所以很容易定位到需要patch的位置。

0x02 SSL握手相关

首先ssl握手的标准流程可以参考这篇文章:http://blog.csdn.net/swjtu100/article/details/52122971

然后我来说一下我这次碰到的情况。
正常的client hello (TLSv1.0):

可以发现服务器的名字包含在SNI里,这样burp在生成服务器证书的时候就可以知道Subject CN应该设置为什么。
以下是正常的server hello:

相反,在ffmpeg中当使用ip地址而不是domain name进行访问时,client会发出如下的client hello数据包:

可以看到这个client hello里并没有domain name,这时burp就出现了bug:

burp在接收到这样的client hello时,直接返回了自己的CA证书,而不是服务器证书。也就是这个CA证书,导致了客户端产生了Unknown CA的Alert。
这次之所以出现问题,就是客户端的访问时使用的ip地址而不是域名,导致了burp出现了这个bug。