WindowsでNpcapのSDKを使ってpcapファイルの送信を行う

Windowsにてpcapファイルにたまったキャプチャデータを再度送出したい場合、色々方法はあるかと思います。昨日Npcap SDKのサンプルを試すやり方を確認しましたので、メモを残します（大丈夫ですよね、Qiitaの使い方間違ってませんよね私…汗）

最初はRawソケットでやろうとしたのですが、どうもWindowsの場合は色々ありそう（↓）ですので…。Npcapを使うのが恐らくトラブルが少ない方法なのではないでしょうか。私駆け出しだから良く知らんけどｗ

https://docs.microsoft.com/ja-jp/windows/win32/winsock/service-provided-raw-sockets-2

**当然の事ではありますが、一応お断りを入れますと、この手の実験はローカルで他人に迷惑をかけないようにやりましょうなのです皆様**

## 環境について

以下の環境で確認しています。また、本記事2020年3月に書いてますので、その頃の状況での内容という事でご理解いただければ。

* Windows 10 Pro(64bit) 1809
* Visual Studio Community 2019 16.5.0 / .Net Framework 4.8.03761
* WireShark v3.2.2
* Npcap 0.9986
* Npcap SDK 1.05

Scapyも少し使いました。

* Ubuntu 18.04.3 LTS
* Python 3.6.9
* Scapy 2.4.3

## まずはScapyでpcapを作る

pcapを作る方ですが、ここではサンプルとしてScapyで作ってみました。Scapy自体は前にもチラッと書いてます。

https://qiita.com/ken_hamada/items/736e1c22f6c40702d1a7

以下、pcapを作成するコードです。PcapWriterを使って２パケットのデータを作ってみました。私はUbuntu18.04上で確認しました。Scapyならそのまま送れるだろーとかツッコミあるかと思いますが、とりあえず見た目が面白いpcap簡単に作れるかなーとか安易に考え、この方法でpcapを作った次第です。

```py

#!/usr/bin/env python
# coding: utf-8

from scapy.all import *
from datetime import datetime
from scapy.utils import PcapWriter
import random

if __name__ == "__main__":

    pcap_file_name = "test.pcap" # この名前で保存
    pcap = PcapWriter(pcap_file_name, append=False, sync=True)

    # Etherレイヤ作成
    ether = Ether()
    Ether.dst = "FF:FF:FF:FF:FF:FF"
    Ether.type = 0x800 # IPv4

    # IPレイヤ作成（他はScapy任せ）
    ip = IP()
    ip.src = "0.0.0.0"
    ip.dst = "255.255.255.255"

    # TCPレイヤ作成（他はScapy任せ）
    random_port = int(random.uniform(32768.0, 63353.00))
    tcp = TCP(sport=random_port, dport=80)
    tcp.flags = "S" # SYN
    tcp.seq = 1000

    # パケットデータ作成    
    packet = ether/ip/tcp
    
    # 1個目書き込み
    pcap.write(packet)

    # 2個目のTCP作成（他はScapy任せ）
    ip.src = "255.255.255.255"
    ip.dst = "0.0.0.0"
    tcp.flags = "SA" # SYN/ACK
    tcp.seq = 5000
    tcp.ack = 1001
    http = "GET /hoge HTTP/1.1\r\n" # Body

    # パケットデータ作成    
    packet = ether/ip/tcp/http

    # 2個目書き込み
    pcap.write(packet)

    print("completed.")

```
これで、0.0.0.0から255.255.255.255へTCP通信するパケットがtest.pcapというファイル名で保存されている筈です。

## Npcap SDKのsencapで送信させる

NpcapとかSDKはここにあります。

https://nmap.org/npcap/

私の場合、Npcap自体はWireSharkと一緒にインストールして、後からSDKを使うという感じで動かしています。

### SDKのビルド

ZIPを　C:\npcap-sdk-0.1　に解凍すると良いです。提供されたVisualStdioのプロジェクトがそこを前提してますので。私の場合ちょっとCドライブは使いたくなかったので、別の場所でやりました。

Examples-remoteのMakeAll.slnをダブルクリックしてVisualStdioを立ち上げます。私の環境ですと「ソリューション操作の再ターゲット」の画面が出て来てソリューションの内容を現環境に向けアップデートしますみたいな趣旨が表示されました。で、「OK」とクリックすれば先に進みます。

後はビルドすれば良いはずです。私はこの中でsendcapだけが欲しかったので、ソリューションエクスプローラからsendcapを右クリックして「ビルド」とする方法でビルドしました。

#### SDKを自分の好きな場所に置いた場合

SDKの展開先をC:\npcap-sdk-0.1ではなく、違う場所においた場合は以下の変更が必要なようです。

* プロジェクトのプロパティ、C/C++の全般「追加のインクルードディレクトリ」のパスを例えば　D:\PCAP_SDK\Include　のように変更します
* 同じくプロジェクトのプロパティ、リンカの全般「追加のライブラリディレクトリ」のパスを例えば　D:\PCAP_SDK\Lib\x64　のように変更します（64bit OSで実行する場合）

で、ビルドするとVisualStdio2019では以下のエラーが出るかと思います。

```
sendcap.c(176,41): error C2065: 'CLK_TCK': 定義されていない識別子です。
```

この場合はsendcap.cの41行目くらいに、time.hのインクールドを追加します。

```cpp
#ifdef WIN32
#include <tchar.h>
#include <time.h> // これを追加

BOOL LoadNpcapDlls()
```

で、ビルド出来るかと思います。64bitリリース版でビルドすると、Examples-remote\x64\Release フォルダにsendcap.exeがいる筈です。

## sendcapで送信

コマンドプロンプトを立ち上げてsendcap.exeを実行すると以下のようにUsageが出てきます。

```
Usage:
         sendcap file_name adapter [s]
```

* adapterはどのネットワークコントローラから出すかです。これの指定方法は後述します。
* file_nameはPCAPのファイルです
* sはオプションで、PCAPファイルのタイムスタンプに同期して送って欲しい場合に使うみたいです。NT系でしか使えないという説明がまぁ…

### アダプタ名

sendcapのusage見るとWimDumpを使えとあります。以下ですね、ここの releases から実行版をダウンロードする事が可能です。

https://github.com/hsluoyz/WinDump

ただし上記だとコンパネの名前との関係が表示されないので、そこも含めて見たい場合はTsharkが使えますのでこちらを紹介します。tshark.exeはWireshark.exeと同じフォルダにあるコンソールアプリです。なので、DOS窓を開いて以下のように打つとアダプタ一覧が出ます（一部省略してます）

```
D:\Program Files\Wireshark>tshark.exe -D
1. \Device\NPF_{A2080ABB-37A9-4CC5-B458-F507672008DE} (VirtualBox Host-Only Network)
（省略）
6. \Device\NPF_{5B6CAC17-469C-4B87-90F7-0E9B5152955D} (繝ｭ繝ｼ繧ｫ繝ｫ 繧ｨ繝ｪ繧｢謗･邯・ 1)
7. \Device\NPF_{05E2E367-3D13-41B2-9234-7CADABDDB5D0} (Wi-Fi)
8. \Device\NPF_Loopback (Adapter for loopback traffic capture)
9. \Device\NPF_{48A6B830-7954-4298-AEC7-0D16FB315C78} (繧､繝ｼ繧ｵ繝阪ャ繝・
```

ま、日本語だと化けるのですが（根本解決は面倒そうなので、コンパネで名前変更で対応するという手抜き対応私はしてます…汗）。それはともかく、今回はWifiがローカルネットワークなので、7の \Device\NPF_{05E2E367-3D13-41B2-9234-7CADABDDB5D0} ですね、これがアダプタ名になります。

### 送出

で、以下のようにするとパケットが送出されます。

```
>sendcap.exe test.pcap \Device\NPF_{05E2E367-3D13-41B2-9234-7CADABDDB5D0}

Elapsed time: 0.000

Total packets generated = 2
Average packets per second = -2147483648

```

メッセージ見ると２パケット出ています。これをWireSharkで観察した結果が以下。ちゃんと255.255.255.255に出ているです。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294469/3e0254eb-54f1-325c-aec2-797fa279714a.png)