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=I
I
是eth0
这样字符串, 指定从网卡抓包, 使用此选项有 root 权限output=F
F
是文件名字符串, 指定输出到指定文件; 否则会输出到 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
}
],
}