What's PCAPNG??

# はじめに
この記事は[ロボP Advent Calendar 2018](https://qiita.com/advent-calendar/2018/robop)の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解析入門](http://slankdev.hatenablog.com/entry/2015/12/22/000000)

# 解析
今回はサンプルとしてこのパケットファイルを解析してみました
[サンプルファイルのリンク](http://goo.gl/QNopW2)
**(リンク切れてたらすみません。。。)**

まずはWiresharkでみる
![Wiresharkで表示](https://qiita-image-store.s3.amazonaws.com/0/148737/763ff40d-c8f6-5992-3fb5-61bd8a2252bf.png)
次に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` でインストール
コードはこんな感じ

~~~Python: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も使っていくとより高度なパケット処理ができそうです。

# 関連ページ
- 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)](http://slankdev.hatenablog.com/entry/2015/12/22/000000)　
    - とても参考になりました。ありがとうございます!
- [Pcapngを読んでみる (https://www.slideshare.net/yagishinnosuke/pcapng)](https://www.slideshare.net/yagishinnosuke/pcapng) 
    - こちらもとても参考になりました。こちらにあるPCAPNGファイルを勝手ながら使わさせていただきました。
- [何が変わった!? Wireshark1.8 (https://www.slideshare.net/morihisa/wireshark-18)](https://www.slideshare.net/morihisa/wireshark-18)
- [PCAP Next Generation (pcapng) Capture File Format(https://pcapng.github.io/pcapng/)](https://pcapng.github.io/pcapng/)