備忘録

備忘録

C#でWinPcapを使う方法(SharpPcapの使い方)

Ⅰ. はじめに

タイトルの通り「C#WinPcapを使う方法(SharpPcapの使い方)」です。
WinPcapを利用したキャプチャを行う為、レイヤ2(データリンク層)レベルでのキャプチャが可能です。

予めWinPcapをインストールする必要があります。
https://www.winpcap.org/default.htm

Ⅱ. やり方

1. NuGetからSharpPcapをインストールする
Install-Package SharpPcap

# .NET Core版
Install-Package SharpPcap.Core
2. サンプルプログラムをコピペする
// https://github.com/chmorgan/sharppcap/blob/master/Examples/Example3.BasicCap/Example3.BasicCap.cs
using SharpPcap;
using SharpPcap.AirPcap;
using SharpPcap.LibPcap;
using SharpPcap.WinPcap;
using System;
using System.Linq;

namespace WinPcapTest
{
  class Program
  {
    public static void Main(string[] args)
    {
      var devices = CaptureDeviceList.Instance;

      if (devices.Count < 1)
      {
        Console.WriteLine("デバイスが見つかりませんでした。");
        return;
      }

      foreach (var dev in devices.Select((val, i) => new { val, i }))
      {
        Console.WriteLine($"({dev.i}) {dev.val.Name} {dev.val.Description}");
      }

      Console.Write("キャプチャ対象のデバイスを選択して下さい: ");
      var deviceIndex = int.Parse(Console.ReadLine());
      var device = devices[deviceIndex];

      device.OnPacketArrival += Device_OnPacketArrival;

      int readTimeoutMilliseconds = 1000;
      switch (device)
      {
        case AirPcapDevice airPcap:
          // NOTE: AirPcap devices cannot disable local capture
          airPcap.Open(OpenFlags.DataTransferUdp, readTimeoutMilliseconds);
          break;
        case WinPcapDevice winPcap:
          winPcap.Open(OpenFlags.DataTransferUdp | OpenFlags.NoCaptureLocal, readTimeoutMilliseconds);
          break;
        case LibPcapLiveDevice livePcapDevice:
          livePcapDevice.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
          break;
        default:
          throw new InvalidOperationException($"unknown device type of {device.GetType().ToString()}");
      }

      device.StartCapture();
      Console.ReadLine();
      device.StopCapture();
      device.Close();
    }

    private static void Device_OnPacketArrival(object sender, CaptureEventArgs e)
    {
      var time = e.Packet.Timeval.Date;
      var length = e.Packet.Data.Length;
      Console.WriteLine($"{time.Hour}:{time.Minute}:{time.Second},{time.Millisecond} Len={length}");
      Console.WriteLine(BitConverter.ToString(e.Packet.Data));
    }
  }
}
実行結果

f:id:kagasu:20180419182408p:plain