Network
Wireshark
tcpdump
pcap
pcapng


はじめに

この記事はロボP Advent Calendar 2018の7日目の記事です。

こんなものもあるんだ〜程度でいいので知ってもらえたらなと思います。


PCAPNGとは?

PCAPNG(PCAP-NextGeneration)とは、名前の通り次世代のPCAPファイルのことであり、libpcapを用いたパケットダンプファイルのフォーマットの一種です。現在Wiresharkではデフォルトのファイルフォーマットになっていますが、あまり世間一般に広がっていません(むしろ敬遠している人がほとんど)


特徴

PCAPファイルと違って以下のような特徴があります。


  • 「ブロック」と呼ばれる単位でデータをまとめている。

  • 複数のインターフェースでキャプチャしたパケットをまとめて格納できる。

  • インターフェース情報や名前解決情報に加え、独自のデータを付与することができる


    • コメントも記述できるのでどういうデータなのかも書ける



PCAPファイルではパケットデータ1つ1つにヘッダが付けられています。一方PCAPNGはヘッダはヘッダ、パケットはパケットとそれぞれ独立しているので、任意のデータにアクセスしたい時速くアクセスできそうですね。Wiresharkでは既に複数のインターフェースでキャプチャしたり、パケットに対してコメントも記述できるようになっています。


構造

まずはPCAPファイルから

(PCAP-FH...PCAP File Header

PCAP-ph...PCAP packet header

PCAP-pd...PCAP packet data と表記させていただきます)

 |--                PCAP-FH              --|--     PCAP-ph     --|-- PCAP-pd --|-- PCAP-ph ...

+-----------------------------------------+---------------------+-------------+-----------------
| magic number,version,timestamp,etc... | TS,packet length | |
+-----------------------------------------+---------------------+-------------+-----------------...
  |                                                                                   |
| PCAPファイルの先頭にある |    PCAPファイルに記録されるパケット。1つ1つのパケットに対してヘッダが付く 
| |

続いてPCAPNGファイル

 |--         section       --|--       section...

+--------------+------------+------------+---
| Block | Block | Block |
+--------------+------------+------------+---...

1セクション毎に複数のブロックが格納されます。セクションが何を指すのかは不明(※Wiresharkは1セクションのみ対応している模様)

ブロックの構造は以下の通り

  0                   1                   2                   3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
| Block Type |
+---------------------------------------------------------------+
| Block Total Length |
+---------------------------------------------------------------+
/ /
/ Block Body /
/ /
+---------------------------------------------------------------+
| Block Total Length |
+---------------------------------------------------------------+

Block Typeには以下のものがあります

Block Type
description

Section Header Block (SHB)
セクションの先頭になるブロック

Interface Description Block (IDB)
インターフェースの詳細情報を格納

Enhanced Packet Block (EPB)
パケットのデータを格納

Simple Packet Block (SPB)
パケットの最小限のデータを格納

Name Resolusion Block (NRB)
名前解決情報などを格納

Interface Statistic Block (ISB)
インターフェース ごとの統計情報を格納

Block BodyにはそれぞれのBlock Typeにあったデータが格納されます。詳しくはこちらを参照

PcapNg解析入門


解析

今回はサンプルとしてこのパケットファイルを解析してみました

サンプルファイルのリンク

(リンク切れてたらすみません。。。)

まずはWiresharkでみる

Wiresharkで表示

次にtcpdumpで

$ sudo tcpdump -r CTF_level3_2.pcapng 

reading from PCAP-NG file CTF_level3_2.pcapng
15:50:27.190053 IP 10.4.216.99 > 192.168.0.1: ICMP echo request, id 64537, seq 0, length 8
15:50:33.900978 IP 10.4.216.99 > 192.168.0.3: ICMP echo request, id 65305, seq 0, length 8
15:50:37.226334 IP 10.4.216.99 > 192.168.0.8: ICMP echo request, id 538, seq 0, length 8
15:50:41.291801 IP 10.4.216.99 > 192.168.0.2: ICMP echo request, id 1306, seq 0, length 8
15:50:47.042493 IP 10.4.216.99 > 192.168.0.9: ICMP echo request, id 2074, seq 0, length 8
15:50:56.503222 IP 10.4.216.99 > 192.168.0.10: ICMP echo request, id 2842, seq 0, length 8
15:50:59.257505 IP 10.4.216.99 > 192.168.0.14: ICMP echo request, id 3610, seq 0, length 8
15:51:29.698767 IP 10.4.216.99 > 192.168.0.39: ICMP echo request, id 4378, seq 0, length 8
15:51:32.571348 IP 10.4.216.99 > 192.168.0.100: ICMP echo request, id 5146, seq 0, length 8
15:51:46.596906 IP 10.4.216.99 > 192.168.0.19: ICMP echo request, id 5914, seq 0, length 8

PCAPファイルとあまり違いがない・・・?

PythonのライブラリにPCAPNGファイルを解析するライブラリがあったので使ってみる

pip install python-pcapng でインストール

コードはこんな感じ


dump_pcapng

import pcapng

import sys

def dump_information(scanner):
for block in scanner:
print(block)

if len(sys.argv) > 1:
with open(sys.argv[1],'rb') as fp:
scanner = pcapng.FileScanner(fp)
dump_information(scanner)
else:
scanner = pcapng.FileScanner(sys.stdin)
dump_information(scanner)


結果はこうなった

$ python dump_pcapng.py CTF_level3_2.pcapng 

<SectionHeader version=1.0 endianness='<' length=-1 options=Options({'shb_os': ['Mac OS X 10.10.3, build 14D131 (Darwin 14.3.0)'], 'shb_userappl': ['Dumpcap 1.12.4 (v1.12.4-0-gb4861da from master-1.12)']})>
<InterfaceDescription link_type=1 reserved=b'\x00\x00' snaplen=262144 options=Options({'if_name': ['en0'], 'if_tsresol': [b'\x06'], 'if_filter': ['\x00icmp'], 'if_os': ['Mac OS X 10.10.3, build 14D131 (Darwin 14.3.0)']})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=1982847269 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c\xdc\xd8\x00\x00@\x01\xfa\xf7\n\x04\xd8c\xc0\xa8\x00\x01\x08\x00\xfb\xe5\xfc\x19\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=1989558194 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c>\x7f\x00\x00@\x01\x99O\n\x04\xd8c\xc0\xa8\x00\x03\x08\x00\xf8\xe5\xff\x19\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=1992883550 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c*D\x00\x00@\x01\xad\x85\n\x04\xd8c\xc0\xa8\x00\x08\x08\x00\xf5\xe5\x02\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=1996949017 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c\x16\x08\x00\x00@\x01\xc1\xc7\n\x04\xd8c\xc0\xa8\x00\x02\x08\x00\xf2\xe5\x05\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2002699709 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1cw\xaf\x00\x00@\x01`\x19\n\x04\xd8c\xc0\xa8\x00\t\x08\x00\xef\xe5\x08\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2012160438 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c\x8a)\x00\x00@\x01M\x9e\n\x04\xd8c\xc0\xa8\x00\n\x08\x00\xec\xe5\x0b\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2014914721 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c:\xfd\x00\x00@\x01\x9c\xc6\n\x04\xd8c\xc0\xa8\x00\x0e\x08\x00\xe9\xe5\x0e\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2045355983 packet_payload_info=(42, 42, b"\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c#?\x00\x00@\x01\xb4k\n\x04\xd8c\xc0\xa8\x00'\x08\x00\xe6\xe5\x11\x1a\x00\x00") options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2048228564 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c\xd4\x12\x00\x00@\x01\x03[\n\x04\xd8c\xc0\xa8\x00d\x08\x00\xe3\xe5\x14\x1a\x00\x00') options=Options({})>
<EnhancedPacket interface_id=0 timestamp_high=332854 timestamp_low=2062254122 packet_payload_info=(42, 42, b'\x00\x00^\x00\x01\x85\x00PV\xf96\x85\x08\x00E\x00\x00\x1c\rB\x00\x00@\x01\xca|\n\x04\xd8c\xc0\xa8\x00\x13\x08\x00\xe0\xe5\x17\x1a\x00\x00') options=Options({})>
<NameResolution records=[{'type': 1, 'address': b'\xc0\xa8\x00\x08', 'name': b'A\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\x0e', 'name': b'N\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\n', 'name': b'_\x00'}, {'type': 1, 'address': b"\xc0\xa8\x00'", 'name': b'R\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\x02', 'name': b'G\x00'}, {'type': 1, 'address': b'\n\x04\xd8c', 'name': b'local\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\x13', 'name': b'}\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\t', 'name': b'{\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00d', 'name': b'B\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\x03', 'name': b'L\x00'}, {'type': 1, 'address': b'\xc0\xa8\x00\x01', 'name': b'F\x00'}] options=Options({})>
<InterfaceStatistics interface_id=0 timestamp_high=332854 timestamp_low=2067314589 options=Options({'opt_comment': ['Counters provided by dumpcap'], 'isb_starttime': [8505803986627269686], 'isb_endtime': [8879048451514766390], 'isb_ifrecv': [10], 'isb_ifdrop': [0]})>

ちゃんとブロックごとに決まったデータが入っていることがわかります。EnhancedPacketのpacket_payload_infoにキャプチャしたパケットがありそうです。(デコードを試みたが文字化けした。。。)


感想

PCAPファイルで十分なのでは? キレイにパケットデータがまとまっていて、自由度もあるみたいなので使いこなせたらネットワークの状況とかがわかりやすいものになるなと思いました。

格納される情報の種類の多さに驚きました。セクションの意味が本当にわかりません

Wiresharkではこの形式がデフォ(形式がこれしかないらしい...)なので、これから使う機会があるかもしれません。


追記

最近ではCTFの問題などで使われているみたいです。(主にForensics、サンプルファイルも恐らくCTF用?)

Scapyも使っていくとより高度なパケット処理ができそうです。


関連ページ


参考にさせて頂いた資料