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 系统为例. 首先需要安装依赖项.

  1. $sudo apt-get install build-essential libssl-dev libpcap-dev libcurl4-openssl-dev

接着进入 joy 根目录, 执行:

  1. $ ./configure --enable-gzip
  2. $ make clean;make

这里启用了 gzip 压缩, 这样编译后的 joy 将会把输出的 JSON 会 gzip 压缩.
编译完成后, 生成的可执行程序等在 bin 子目录. sleuth 是一个 Python 工具, 它不需要编译, 本来就在根目录中.

基本使用

目前仅讨论 joy 工具的使用.
joy 通过命令行参数来完成不同的工作. 它的基本语法是:

  1. $joy [options] [file1 [file2 ... ]]

joy 的默认输出是 gzip 压缩的 JSON 格式, 所以要查看结果需要进行解压缩, 比如这样使用:

  1. $ joy browse.pcap | gunzip

选项部分除了 -x 外都是 key=value 的形式, 其中 value 一般是数字, 字符串或布尔值. 常用选项有:

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

  1. $./joy bidir=1 http=1 ../test/pcaps/firefox58.pcap | gunzip > firefox58.json

这里没有使用 output=F 选项, 因为那样生成的文件还是 gzip 压缩文件, 这里直接使用重定向解压缩了.
生成的 JSON 文件中包括很多行, 其中每一行是一个完整的 JSON, 如果把整个文件放到 JSON 格式化工具中, 是会报错的, 因为它是多个完整 JSON 对象的合并. 其中某一行为:

  1. {
  2. "sa": "10.225.201.111",
  3. "da": "172.217.3.46",
  4. "pr": 6,
  5. "sp": 57508,
  6. "dp": 80,
  7. "bytes_out": 429,
  8. "num_pkts_out": 6,
  9. "bytes_in": 706,
  10. "num_pkts_in": 4,
  11. "time_start": 1516683628.963303,
  12. "time_end": 1516683630.784586,
  13. "packets": [{
  14. "b": 429,
  15. "dir": ">",
  16. "ipt": 20
  17. },
  18. {
  19. "b": 706,
  20. "dir": "<",
  21. "ipt": 23
  22. }
  23. ],
  24. "ip": {
  25. "out": {
  26. "ttl": 64,
  27. "id": [
  28. 28378,
  29. 28379,
  30. 28380,
  31. 28381,
  32. 28382,
  33. 28383
  34. ]
  35. },
  36. "in": {
  37. "ttl": 55,
  38. "id": [
  39. 6551,
  40. 6557,
  41. 6566,
  42. 7581
  43. ]
  44. }
  45. },
  46. "tcp": {
  47. "first_seq": 1098031007,
  48. "out": {
  49. "flags": "S",
  50. "first_window_size": 29200,
  51. "opt_len": 20,
  52. "opts": [{
  53. "mss": 1460
  54. },
  55. {
  56. "sackp": null
  57. },
  58. {
  59. "ts": {
  60. "val": 2207969605,
  61. "ecr": 0
  62. }
  63. },
  64. {
  65. "noop": null
  66. },
  67. {
  68. "ws": 7
  69. }
  70. ]
  71. },
  72. "in": {
  73. "flags": "SA",
  74. "first_window_size": 42408,
  75. "opt_len": 20,
  76. "opts": [{
  77. "mss": 1380
  78. },
  79. {
  80. "sackp": null
  81. },
  82. {
  83. "ts": {
  84. "val": 3313274154,
  85. "ecr": 2207969605
  86. }
  87. },
  88. {
  89. "noop": null
  90. },
  91. {
  92. "ws": 8
  93. }
  94. ]
  95. }
  96. },
  97. "http": [{
  98. "out": [{
  99. "method": "POST"
  100. },
  101. {
  102. "uri": "/ocsp"
  103. },
  104. {
  105. "version": "HTTP/1.1"
  106. },
  107. {
  108. "Host": "clients1.google.com"
  109. },
  110. {
  111. "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0"
  112. },
  113. {
  114. "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
  115. },
  116. {
  117. "Accept-Language": "en-US,en;q=0.5"
  118. },
  119. {
  120. "Accept-Encoding": "gzip, deflate"
  121. },
  122. {
  123. "Content-Length": "75"
  124. },
  125. {
  126. "Content-Type": "application/ocsp-request"
  127. },
  128. {
  129. "Connection": "keep-alive"
  130. },
  131. {
  132. "body": "30493047304530433041300906052b0e"
  133. }
  134. ],
  135. "in": [{
  136. "version": "HTTP/1.1"
  137. },
  138. {
  139. "code": "200"
  140. },
  141. {
  142. "reason": "OK"
  143. },
  144. {
  145. "Content-Type": "application/ocsp-response"
  146. },
  147. {
  148. "Date": "Tue, 23 Jan 2018 05:00:28 GMT"
  149. },
  150. {
  151. "Cache-Control": "public, max-age=345600"
  152. },
  153. {
  154. "Server": "ocsp_responder"
  155. },
  156. {
  157. "Content-Length": "463"
  158. },
  159. {
  160. "X-XSS-Protection": "1; mode=block"
  161. },
  162. {
  163. "X-Frame-Options": "SAMEORIGIN"
  164. },
  165. {
  166. "body": "308201cb0a0100a08201c4308201c006"
  167. }
  168. ]
  169. }]
  170. }

提取TLS信息

  1. $./joy bidir=1 tls=1 ../test/pcaps/tls12.pcap | gunzip > tls12.json

输出的 JSON 文件中的 TLS 信息(截取):

  1. "tls": {
  2. "c_version": 5,
  3. "s_version": 5,
  4. "c_key_length": 528,
  5. "c_key_exchange": "41043d7da42b5f57684b396b1a8bd0a9dc1b3e8dc37b9a79efb8c42e2f6ee6a49652ba20a5bb7a4d7e372e59b57621fae64b2dac596c16459a6a92ba4933a5cb34b5",
  6. "c_random": "146e9c81bd6b67b4c4f7629f3136fba718735ac35034827fb45b59d38e51c91d",
  7. "s_random": "0e2625b7b76e1ed2b19e61b5d06811ed46ee8c847b852cd070c2a4e4ff450caa",
  8. "scs": "c030",
  9. "cs": [
  10. "c030",
  11. "c02c",
  12. "c028",
  13. "000a",
  14. "00ff"
  15. ],
  16. "c_extensions": [
  17. {
  18. "ec_point_formats": "03000102"
  19. },
  20. {
  21. "supported_groups": "001a00170019001c001b0018001a0016000e000d000b000c0009000a"
  22. },
  23. {
  24. "session_ticket": ""
  25. },
  26. {
  27. "signature_algorithms": "001e060106020603050105020503040104020403030103020303020102020203"
  28. },
  29. {
  30. "heartbeat": "01"
  31. }
  32. ],
  33. "s_extensions": [
  34. {
  35. "renegotiation_info": "00"
  36. },
  37. {
  38. "ec_point_formats": "03000102"
  39. },
  40. {
  41. "session_ticket": ""
  42. },
  43. {
  44. "heartbeat": "01"
  45. }
  46. ],
  47. "s_cert": [
  48. {
  49. "length": 1025,
  50. "serial_number": "c062cf36806feb0d",
  51. "signature": "32851463a79d43c452543e9783368379fd0628d4714f8f723fd00515dc71da91d1ce0264a70306ba675316bf1306157beb0ef52206e80f6318e3315f3820213406f03cf4eff57a35f03341a1e20eb2835666640a3a6cef5a1556c883970c1bb39a67d3cbb3d762bcaae1374062bbfa5ff5c77d5c96f4a6368496cbe123d5b3565bfb83fb12e0ffe00c42a95947a3744ff05d04d0c4bfb90ce616240a9fed22e4702f87e8e3a1c909700012b10cd25f132503e3afa06b3260b3c2f4d27de1dc3a7c081bcd209ba73385ba2995e7dcd285e0a0daab0e6a53301e94f64940c8082335ec5e22eeaaaa8e8715a0a51beace06ccf0de3c6ba4b69457e86602a998f5b3",
  52. "signature_algo": "sha256WithRSAEncryption",
  53. "signature_key_size": 2048,
  54. "issuer": [
  55. {
  56. "countryName": "US"
  57. },
  58. {
  59. "stateOrProvinceName": "California"
  60. },
  61. {
  62. "localityName": "Las Angeles"
  63. },
  64. {
  65. "organizationName": "Internet Widgits Pty Ltd"
  66. },
  67. {
  68. "commonName": "server.blah.com"
  69. },
  70. {
  71. "emailAddress": "teddy@blah.com"
  72. }
  73. ],
  74. "subject": [
  75. {
  76. "countryName": "US"
  77. },
  78. {
  79. "stateOrProvinceName": "California"
  80. },
  81. {
  82. "localityName": "Las Angeles"
  83. },
  84. {
  85. "organizationName": "Internet Widgits Pty Ltd"
  86. },
  87. {
  88. "commonName": "server.blah.com"
  89. },
  90. {
  91. "emailAddress": "teddy@blah.com"
  92. }
  93. ],
  94. "extensions": [
  95. {
  96. "X509v3 Subject Key Identifier": "F8:99:15:30:3E:1D:E5:E8:39:EF:EF:CE:74:48:D0:62:17:AA:0E:60"
  97. },
  98. {
  99. "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."
  100. },
  101. {
  102. "X509v3 Basic Constraints": "CA:TRUE"
  103. }
  104. ],
  105. "validity_not_before": "Aug 7 15:04:17 2017 GMT",
  106. "validity_not_after": "Aug 7 15:04:17 2018 GMT",
  107. "subject_public_key_algo": "rsaEncryption",
  108. "subject_public_key_size": 2048
  109. }
  110. ],
  111. }

参考