はじめに
この記事はロボ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解析入門
解析
今回はサンプルとしてこのパケットファイルを解析してみました
サンプルファイルのリンク
(リンク切れてたらすみません。。。)
$ 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
でインストール
コードはこんな感じ
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も使っていくとより高度なパケット処理ができそうです。
関連ページ
- python-pcapng Sample Code (https://github.com/rshk/python-pcapng/blob/master/examples/dump_pcapng_info.py)
参考にさせて頂いた資料
-
PcapNg解析入門 (http://slankdev.hatenablog.com/entry/2015/12/22/000000)
- とても参考になりました。ありがとうございます!
-
Pcapngを読んでみる (https://www.slideshare.net/yagishinnosuke/pcapng)
- こちらもとても参考になりました。こちらにあるPCAPNGファイルを勝手ながら使わさせていただきました。
- 何が変わった!? Wireshark1.8 (https://www.slideshare.net/morihisa/wireshark-18)
- PCAP Next Generation (pcapng) Capture File Format(https://pcapng.github.io/pcapng/)