前言
Android系统上抓包HTTPS是不是越来越难了?高版本无法添加CA证书,抓包软件依赖太多,VPN模式、或HOOK程序时,会被APP检测到。对抗成本愈加增高。有什么万能的工具吗?
是的,eCapture for Android[1]来了。以后在Android上抓HTTPS通讯包,再也不用安装CA证书了,再也不用下载一堆python依赖环境了,再也不用重打包ssl类库了,再也不用改一堆手机参数了,一键启用,简单明了。
(资料图)
eCapture简介
eCapture是一款无需CA证书即可抓获HTTPS明文的软件。支持pcapng格式,支持Wireshark直接查看。基于eBPF技术,仅需root权限,即可一键抓包。eCapture中文名旁观者,即 当局者迷,旁观者清。
2022年年初上海疫情期间,笔者开始编写并开源[2],至今已经半年,GitHub上已经 4200个星星。
eCapture是基于eBPF技术实现的抓包软件,依赖系统内核是否支持eBPF。目前支持在操作系统上,支持了X86_64\ARM64的Linux kernel 4.18以上内核,支持了ARM64 Android(Linux) kernel 5.4以上版本。最新版是在2022年9月9日发布的v0.4.3版本。
演示视频
下载后,一条命令启动,干净利索。./ecapture tls -w ecapture.pcapng
先看演示视频,演示环境为Ubuntu 21.04、Android 5.4 (Pixel 6)。
模块功能
eCapture支持tls、bash、mysqld、postgres等模块的信息提取与捕获。本文仅讨论tls这个HTTPS/TLS明文捕获模块。
加密通讯明文捕获--tls模块
tls模块在加密通讯类库上,支持了openssl、gnutls、nspr/nss、boringssl等类库。但在Android上,pcapng模式只支持boringssl,文本模式则都支持。
如何使用eCapture
环境依赖
操作系统 Linux kernel 4.18以上,Android kernel 5.4以上。支持BPF,可选支持BTF(eCapture版本不同)root权限版本选择
BPF CO-RE[3]特性为BTF通用的格式,用于做跨内核版本兼容。有的Android手机是没开启BTF。可以查看系统配置确认,CONFIG_DEBUG_INFO_BTF=y为开启;CONFIG_DEBUG_INFO_BTF=n为关闭;其他为不支持BPF,无法使用eCapture。
cfc4n@vm-server:~$#cat/boot/config-`uname-r`|grepCONFIG_DEBUG_INFO_BTFCONFIG_DEBUG_INFO_BTF=yAndroid系统上,config是gzip压缩的,且配置文件目录也变了。可使用zcat /proc/config.gz命令代替。
eCapture默认发行了支持CO-RE的ELF程序。Android版会发行一个5.4内核不支持BTF(即没有CO-RE)的版本。下载后,可以通过./ecapture -v确认。非CO-RE版本的version信息中包含编译时的内核版本。
# no CO-REeCapture version:linux_aarch64:0.4.2-20220906-fb34467:5.4.0-104-generic# CO-REeCapture version:linux_aarch64:0.4.2-20220906-fb34467:[CORE]若版本不符合自己需求,可以自行编译,步骤见文末。
全局参数介绍
全局参数重点看如下几个
root@vm-server:/home/cfc4n/#ecapture-h--hex[=false]printbytestringsashexencodedstrings-l,--log-file=""-lsavethepacketstofile-p,--pid=0ifpidis0thenwetargetallpids-u,--uid=0ifuidis0thenwetargetallusers--hex用于stdout输出场景,展示结果的十六进制,用于查看非ASCII字符,在内容加密、编码的场景特别有必要。-l, --log-file=保存结果的文件路径。-p, --pid=0捕获的目标进程,默认为0,则捕获所有进程。-u, --uid=0捕获的目标用户,默认为0,则捕获所有用户,对Android来说,是很需要的参数。模块参数
root@vm-server:/home/cfc4n/project/ssldump#bin/ecapturetls-hOPTIONS:--curl=""curlorwgetfilepath,usetodectetopenssl.sopath,default:/usr/bin/curl--firefox=""firefoxfilepath,default:/usr/lib/firefox/firefox.--gnutls=""libgnutls.sofilepath,willautomaticallyfinditfromcurldefault.--gobin=""pathtobinarybuiltwithGotoolchain.-h,--help[=false]helpfortls-i,--ifname=""(TCClassifier)Interfacenameonwhichtheprobewillbeattached.--libssl=""libssl.sofilepath,willautomaticallyfinditfromcurldefault.--nspr=""libnspr44.sofilepath,willautomaticallyfinditfromcurldefault.--port=443portnumbertocapture,default:443.--pthread=""libpthread.sofilepath,usetohookconnecttocapturesocketFD.willautomaticallyfinditfromcurl.--wget=""wgetfilepath,default:/usr/bin/wget.-w,--write=""writetherawpacketstofileaspcapngformat.-i参数
-i参数为网卡的名字,Linux上默认为eth0,Android上默认为wlan0,你可以用这个参数自行指定。
输出模式
输出格式支持两种格式,文本跟pcapng文件。有三个参数,
默认,全局参数,输出文本结果到stdout-l全局参数,保存文本结果的文件路径-w仅tls模块参数,保存pcapng结果的文件路径类库路径
Linux上支持多种类库,不同类库的路径也不一样。
| 类库 | 参数路径 | 默认值 |
|---|---|---|
| openssl/boringssl | --libssl | Linux自动查找,Android为/apex/com.android.conscrypt/lib64/libssl.so |
| gnutls | --gnutls | Linux自动查找,Android pcapng模式暂未支持 |
| nspr/nss | --nspr | Linux自动查找,Android pcapng模式暂未支持 |
文本模式
-l或者不加 -w参数将启用该模式。
支持openssl、boringssl、gnutls、nspr/nss等多种TLS加密类库。支持DTLS、TLS1.0至TLS1.3等所有版本的加密协议。支持-p、-u等所有全局过滤参数。
pcapng模式
-w参数启用该模式,并用-i选择网卡名,Linux系统默认为eth0,Android系统默认为wlan0,
仅支持openssl、boringssl两个类库的数据捕获。暂不支持TLS 1.3协议。
类库与参数支持
在Linux系统上,大部分类库与参数都是可以支持的。但在Android系统上,因为内核与ARM架构的原因,支持的参数上,有一定的差异。
不同模式的参数支持
-p、-u两个全局参数,支持文本模式,不支持pcapng模式。这是因为pcapng模式是使用eBPF TC技术实现。
| 模式 | -p | -u | --libssl | --port |
|---|---|---|---|---|
| 文本 | ✅ | ✅ | ✅ | ✅ |
| pcapng | ❌ | ❌ | ✅ | ✅ |
不同模式的类库以协议支持
| 模式 | openssl(类库) | boringssl(类库) | TLS 1.0/1.1/1.2(协议) | TLS 1.3(协议) |
|---|---|---|---|---|
| 文本 | ✅ | ✅ | ✅ | ✅ |
| pcapng | ✅ | ✅ | ✅ | ❌ |
pcapng模式暂时不支持TLS 1.3,TLS 1.3密钥捕获功能[4]已经开发完成,只是遇到一些BUG,还在解决中。笔者不是openssl的专家,对TLS 协议也不太熟。需要补充这两块的知识,解决起来成本比较高,也欢迎对这块擅长的朋友一起来解决。
与tcpdump联合使用
eCapture基于eBPF TC,实现了流量捕获,并保存到pcapng文件中。基于eBPF Uprobe实现了TLS Master Secret的捕获。并基于Wireshark的Decryption Secrets Block (DSB)[5]标准,实现了gopacket的DSB功能[6],合并网络包与密钥,保存到pcapng中。
eCapture在网络包捕获上,没有tcpdump强大,不支持丰富的参数。你可以用eCapture捕获master secrets,用tcpdump捕获网络包,然后使用wiresahrk自定义设置密钥文件,配合使用。
网络包捕获
tcpdump 的常规用法,不再赘述。
密钥捕获
同时启用ecapture ,模式可以选文本或者pcapng,都会保存TLS的master secrets密钥数据到ecapture_masterkey.log中。
网络包查看
用Wireshark打开网络包文件,设置这个master key文件,之后就可以看到TLS解密后的明文了。
配置路径:Wireshark--> Preferences--> Protocols--> TLS--> (Pre)-Master-Secret log filename
参数
指定路径
默认路径
在Android上,Google使用了boring ssl类库,也就是C++语言在libssl基础上的包装。默认情况下,会使用/apex/com.android.conscrypt/lib64/libssl.so路径。
APP的类库确认
你可以使用lsof -p {APP PID}|grep libssl来确认。若不是默认路径,则可以使用--libssl参数来指定。
高级用法
如果你需要查看的APP是自定义SSL类库,那么你可以自助修改eCapture来实现。
自定义函数名与offset
首先,需要确定HOOK函数的函数名或者符号表地址。
没有源码
如果你没有目标类库的源码,可以通过IDA等软件静态分析、动态调试,确定SSL Write的地址offset。在配置填写在user/module/probe_openssl.go文件中,对应的probe配置部分。
{Section:"uprobe/SSL_write",EbpfFuncName:"probe_entry_SSL_write",AttachToFuncName:"SSL_write",UprobeOffset:0xFFFF00,//TODOBinaryPath:binaryPath,},offset自动计算
如果你有源码,则可以自行阅读源码确定函数名或者符号表的地址。对于结构体的成员属性读取,则可以通过offsetof宏来自动计算。通过偏移量的方式,读取内容。
//g++-Iinclude/-Isrc/./src/offset.c-ooff#include #include #include#include#include#defineSSL_STRUCT_OFFSETS\X(ssl_st,session)\X(ssl_st,s3)\X(ssl_session_st,secret)\X(ssl_session_st,secret_length)\X(bssl::SSL3_STATE,client_random)\X(bssl::SSL_HANDSHAKE,new_session)\X(bssl::SSL_HANDSHAKE,early_session)\X(bssl::SSL3_STATE,hs)\X(bssl::SSL3_STATE,established_session)\X(bssl::SSL_HANDSHAKE,expected_client_finished_)structoffset_test{/*data*/intt1;bssl::UniquePtrsession;};intmain(){printf("typedefstructssl_offsets{//DEF\n");#defineX(struct_name,field_name)\printf("int"#struct_name"_"#field_name";//DEF\n");SSL_STRUCT_OFFSETS#undefXprintf("}ssl_offsets;//DEF\n\n");printf("/*%s*/\nssl_offsetsopenssl_offset_%d={\n",OPENSSL_VERSION_TEXT,OPENSSL_VERSION_NUMBER);#defineX(struct_name,field_name)\printf("."#struct_name"_"#field_name"=%ld,\n",\offsetof(structstruct_name,field_name));SSL_STRUCT_OFFSETS#undefXprintf("};\n");return0;} 参数提取
对于参数,你需要确认被HOOK函数的参数类型,以便确认读取方式,可以参考kern/openssl_kern.c内的SSL_write函数实现。
编译
ARM Linux 编译
公有云厂商大部分都提供了ARM64 CPU服务器,笔者选择了腾讯云的。在广州六区中,名字叫标准型SR1(SR1即ARM 64CPU),最低配的SR1.MEDIUM22核2G即满足编译环境。可以按照按量计费方式购买,随时释放,比较划算。
操作系统选择ubuntu 20.04 arm64。
ubuntu@VM-0-5-ubuntu:~$sudoapt-getupdateubuntu@VM-0-5-ubuntu:~$sudoapt-getinstall--yeswgetgitgolangbuild-essentialpkgconflibelf-devllvm-12clang-12linux-tools-genericlinux-tools-commonubuntu@VM-0-5-ubuntu:~$wgethttps://golang.google.cn/dl/go1.18.linux-arm64.tar.gzubuntu@VM-0-5-ubuntu:~$sudorm-rf/usr/local/go&&sudotar-C/usr/local-xzfgo1.18.linux-arm64.tar.gzubuntu@VM-0-5-ubuntu:~$fortoolin"clang""llc""llvm-strip"dosudorm-f/usr/bin/$toolsudoln-s/usr/bin/$tool-12/usr/bin/$tooldoneubuntu@VM-0-5-ubuntu:~$exportGOPROXY=https://goproxy.cnubuntu@VM-0-5-ubuntu:~$exportPATH=$PATH:/usr/local/go/bin编译方法
ANDROID=1 make命令编译支持core版本的二进制程序。ANDROID=1 make nocore命令编译仅支持当前内核版本的二进制程序。当Wireshark遇到eBPF
+ =贡献者
感谢chriskaliX 、chenhengqi、vincentmli、huzai9527、yihong0618、sfx(4ft35t)等朋友的贡献。感谢tiann Weishu在Android这个需求上的推动。
招聘
美团信息安全部,某项目组Leader直招,没有中间商赚差价。北京上海两地任选,面向RASP、HIDS产品,JVM、Linux内核入侵检测等安全研发职位
JAVA资深研发工程师golang高级工程师更多职位见 https://www.cnxct.com/jobs/[7]参考资料
[1]
eCapture for Android:https://ecapture.cc
[2]
笔者开始编写并开源:https://www.cnxct.com/what-is-ecapture/
[3]
CO-RE:https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html
[4]
TLS 1.3密钥捕获功能:https://github.com/ehids/ecapture/pull/143
[5]
Decryption Secrets Block (DSB):https://github.com/pcapng/pcapng/pull/54
[6]
gopacket的DSB功能:https://github.com/google/gopacket/pull/1042
[7]
https://www.cnxct.com/jobs/:https://www.cnxct.com/jobs/?f=wxg