Joy 是 Cisco 公司的开源软件包, 它包括数据收集工具 joy, 以及 sleuth 等分析工具. joy 是一个 C 程序, (通过 libpcap) 可以从离线 pcap 文件或从网卡读取报文, 进行分析后用 JSON 格式输出提取的信息. sleuth 是一个 Python 程序, 用于对输出的 JSON 信息进行进一步的分析过滤.
Joy 可以对网络数据进行收集, 分析和挖掘, 主要特性:
- 支持对 HTTP, TLS, DNS, DHCP 等重要协议进行元数据(metadata)提取
- 输出为 JSON 格式, 可以被很多分析工具和编程环境支持, 比如 Python 和机器学习框架
- 支持 Linux, macOS, Windows 等操作系统
所以 Joy 的价值在于元数据提取和基于 JSON 的数据分析, 和 wireshark, tcpdump 等协议分析工具有不同的特点.
joy 源码主目录的 doc 子目录中有一些文档, 可供参考.
编译
以 Ubuntu 系统为例. 首先需要安装依赖项.
$sudo apt-get install build-essential libssl-dev libpcap-dev libcurl4-openssl-dev
接着进入 joy 根目录, 执行:
$ ./configure --enable-gzip$ make clean;make
这里启用了 gzip 压缩, 这样编译后的 joy 将会把输出的 JSON 会 gzip 压缩.
编译完成后, 生成的可执行程序等在 bin 子目录. sleuth 是一个 Python 工具, 它不需要编译, 本来就在根目录中.
基本使用
目前仅讨论 joy 工具的使用.
joy 通过命令行参数来完成不同的工作. 它的基本语法是:
$joy [options] [file1 [file2 ... ]]
joy 的默认输出是 gzip 压缩的 JSON 格式, 所以要查看结果需要进行解压缩, 比如这样使用:
$ joy browse.pcap | gunzip
选项部分除了 -x 外都是 key=value 的形式, 其中 value 一般是数字, 字符串或布尔值. 常用选项有:
interface=II是eth0这样字符串, 指定从网卡抓包, 使用此选项有 root 权限output=FF是文件名字符串, 指定输出到指定文件; 否则会输出到 stdoutbpf=expression指定 BPF 包过滤器, 和 wireshark 抓包时的过滤器一样bidir=1为 1 时将把一条流的双向合并输出, 为 0 时则分开输出dist=1输出载荷中的字节分布, 比如 0x1a 出现过多少次exe=1输出流所对应的进程名, 仅当 joy 在此进程所在的主机上运行时可用dns=1 dhcp=1 http=1 tls=1等 输出指定协议的元数据payload=N以 16进制输出首个数据报文的前 N 个载荷, N<=32
实例
Joy 的子目录 test/pcaps 下包含一些测试用的 pcap 文件, 下面就以其中的两个文件为例.
提取HTTP信息
$./joy bidir=1 http=1 ../test/pcaps/firefox58.pcap | gunzip > firefox58.json
这里没有使用 output=F 选项, 因为那样生成的文件还是 gzip 压缩文件, 这里直接使用重定向解压缩了.
生成的 JSON 文件中包括很多行, 其中每一行是一个完整的 JSON, 如果把整个文件放到 JSON 格式化工具中, 是会报错的, 因为它是多个完整 JSON 对象的合并. 其中某一行为:
{"sa": "10.225.201.111","da": "172.217.3.46","pr": 6,"sp": 57508,"dp": 80,"bytes_out": 429,"num_pkts_out": 6,"bytes_in": 706,"num_pkts_in": 4,"time_start": 1516683628.963303,"time_end": 1516683630.784586,"packets": [{"b": 429,"dir": ">","ipt": 20},{"b": 706,"dir": "<","ipt": 23}],"ip": {"out": {"ttl": 64,"id": [28378,28379,28380,28381,28382,28383]},"in": {"ttl": 55,"id": [6551,6557,6566,7581]}},"tcp": {"first_seq": 1098031007,"out": {"flags": "S","first_window_size": 29200,"opt_len": 20,"opts": [{"mss": 1460},{"sackp": null},{"ts": {"val": 2207969605,"ecr": 0}},{"noop": null},{"ws": 7}]},"in": {"flags": "SA","first_window_size": 42408,"opt_len": 20,"opts": [{"mss": 1380},{"sackp": null},{"ts": {"val": 3313274154,"ecr": 2207969605}},{"noop": null},{"ws": 8}]}},"http": [{"out": [{"method": "POST"},{"uri": "/ocsp"},{"version": "HTTP/1.1"},{"Host": "clients1.google.com"},{"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0"},{"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},{"Accept-Language": "en-US,en;q=0.5"},{"Accept-Encoding": "gzip, deflate"},{"Content-Length": "75"},{"Content-Type": "application/ocsp-request"},{"Connection": "keep-alive"},{"body": "30493047304530433041300906052b0e"}],"in": [{"version": "HTTP/1.1"},{"code": "200"},{"reason": "OK"},{"Content-Type": "application/ocsp-response"},{"Date": "Tue, 23 Jan 2018 05:00:28 GMT"},{"Cache-Control": "public, max-age=345600"},{"Server": "ocsp_responder"},{"Content-Length": "463"},{"X-XSS-Protection": "1; mode=block"},{"X-Frame-Options": "SAMEORIGIN"},{"body": "308201cb0a0100a08201c4308201c006"}]}]}
提取TLS信息
$./joy bidir=1 tls=1 ../test/pcaps/tls12.pcap | gunzip > tls12.json
输出的 JSON 文件中的 TLS 信息(截取):
"tls": {"c_version": 5,"s_version": 5,"c_key_length": 528,"c_key_exchange": "41043d7da42b5f57684b396b1a8bd0a9dc1b3e8dc37b9a79efb8c42e2f6ee6a49652ba20a5bb7a4d7e372e59b57621fae64b2dac596c16459a6a92ba4933a5cb34b5","c_random": "146e9c81bd6b67b4c4f7629f3136fba718735ac35034827fb45b59d38e51c91d","s_random": "0e2625b7b76e1ed2b19e61b5d06811ed46ee8c847b852cd070c2a4e4ff450caa","scs": "c030","cs": ["c030","c02c","c028","000a","00ff"],"c_extensions": [{"ec_point_formats": "03000102"},{"supported_groups": "001a00170019001c001b0018001a0016000e000d000b000c0009000a"},{"session_ticket": ""},{"signature_algorithms": "001e060106020603050105020503040104020403030103020303020102020203"},{"heartbeat": "01"}],"s_extensions": [{"renegotiation_info": "00"},{"ec_point_formats": "03000102"},{"session_ticket": ""},{"heartbeat": "01"}],"s_cert": [{"length": 1025,"serial_number": "c062cf36806feb0d","signature": "32851463a79d43c452543e9783368379fd0628d4714f8f723fd00515dc71da91d1ce0264a70306ba675316bf1306157beb0ef52206e80f6318e3315f3820213406f03cf4eff57a35f03341a1e20eb2835666640a3a6cef5a1556c883970c1bb39a67d3cbb3d762bcaae1374062bbfa5ff5c77d5c96f4a6368496cbe123d5b3565bfb83fb12e0ffe00c42a95947a3744ff05d04d0c4bfb90ce616240a9fed22e4702f87e8e3a1c909700012b10cd25f132503e3afa06b3260b3c2f4d27de1dc3a7c081bcd209ba73385ba2995e7dcd285e0a0daab0e6a53301e94f64940c8082335ec5e22eeaaaa8e8715a0a51beace06ccf0de3c6ba4b69457e86602a998f5b3","signature_algo": "sha256WithRSAEncryption","signature_key_size": 2048,"issuer": [{"countryName": "US"},{"stateOrProvinceName": "California"},{"localityName": "Las Angeles"},{"organizationName": "Internet Widgits Pty Ltd"},{"commonName": "server.blah.com"},{"emailAddress": "teddy@blah.com"}],"subject": [{"countryName": "US"},{"stateOrProvinceName": "California"},{"localityName": "Las Angeles"},{"organizationName": "Internet Widgits Pty Ltd"},{"commonName": "server.blah.com"},{"emailAddress": "teddy@blah.com"}],"extensions": [{"X509v3 Subject Key Identifier": "F8:99:15:30:3E:1D:E5:E8:39:EF:EF:CE:74:48:D0:62:17:AA:0E:60"},{"X509v3 Authority Key Identifier": "keyid:F8:99:15:30:3E:1D:E5:E8:39:EF:EF:CE:74:48:D0:62:17:AA:0E:60."},{"X509v3 Basic Constraints": "CA:TRUE"}],"validity_not_before": "Aug 7 15:04:17 2017 GMT","validity_not_after": "Aug 7 15:04:17 2018 GMT","subject_public_key_algo": "rsaEncryption","subject_public_key_size": 2048}],}
