例子,cloudflare的warp-svc.exe。抓包获取密钥。
用proxifier尝试了一下强行代理,无效,因为proxifier是通过Hook Socket函数方式实现的,但这个程序可能没有用Socket函数进行通信。
之后发现通过nekoray基于gvisor的VPN白名单模式全局路由可以强制代理。但发现MITMproxy抓不了包而且在Event Log返回sslv3 alert bad certificate。
这说明warp-svc.exe在和MITMproxy 进行ssl握手的时候发现MITMproxy 的证书不对,然后就向MITMproxy发送sslv3 alert 信息然后中断连接。问题是,我已经将MITMproxy 的证书存储到windows的根证书目录里面,但仍然出现这种情况,说明warp-svc.exe内部固定了证书发行机构。
尝试了google的ssl_log,无效,ssl_log的原理是hook openssl库,可能这个程序没有用openssl库来处理tls。
过IDA pro查看发现有很多cargo的字样,猜测是rust写的。进一步搜索alert 发现一个字符串"Sending warning alert",网上一查发现是rustls库里的字符串,那么就从rustls入手。
先从bad certificate开始搜索rustls的源码,由于bad certificate在ssl握手里的序号是42,
42是0x2a,先搜索0x2a
发现是个枚举类型,接着搜索BadCertificate发现有三种类型对应这个alertBadEncoding | UnhandledCriticalExtension | NotValidForName
前面两个错误不太可能发生,那么NotValidForName最可能,接着搜索发现在pkierror里面:
接着搜索pki_error
发现确实有固定证书的情况,就是self.roots的这个变量。发现确实内部固定了根证书:
接着搜索RootCertStore,发现在anchors命名空间里
去anchors命名空间里翻找发现结构体RootCertStore是OwnedTrustAnchor类型是vector数组
接着搜索OwnedTrustAnchor找到它的结构体
那么RootCertStore 是从哪里赋值的呢?代码里没搜到,通过readme可以看到,example里面有个tlsclient-mio.rs,应该是调用rustls的例子:
从里面可以看到RootCertStore 被webpki_roots::TLS_SERVER_ROOTS所赋值,于是去寻找webpki_roots发现确实有这样一个项目,这个项目里面有个脚本build.py,生成了src/lib.rs文件,进入这个文件一看:
发现根证书的存储方式是存储subject和spki,这两个值通过src/bin
/process_cert.rs这个程序处理证书然后生成,通过cargo build之后在target文件夹里面生成的process_cert.exe文件。
其中每个证书的spki大小都只有几种,而subject大小不一样。去IDA里面搜索subject代表的二进制数值,果然搜到了。
之后的思路就简单了,直接用openssl生成一个相同大小subject和spki的的证书然后使用process_cert.exe提取出来,再使用010editor替换目标程序warp-svc.exe里面的字节串即可。一个简单的方法是使用与你的目标域名的签发机构根证书相同的生成信息,比如api.cloudflareclient.com的根证书是Baltimore CyberTrust Root,提取出来后使用命令
openssl x509 -in '.\Baltimore CyberTrust Root.crt' -noout -text
得到它的subject:
Subject: C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
然后使用openssl生成subject一模一样的证书
openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt
#按照之前提取的信息填写
cat ca.key ca.crt >mitmproxy-ca.pem
最后用process_cert.exe处理这个证书提取出二进制格式的subject和spki并使用010editor替换目标程序warp-svc.exe里面的字节串。
将这个证书安装到系统根证书目录之后就能抓包解密流量了,需要注意的是如果抓不到包,则可能是因为域名解析的地址是ipv6的因为nekoray里的ipv6vpn有些bug。