高速通信計算研究所

slankdevの報告

パケット遊び ARP編

この記事は僕の趣味である「パケット遊び」をたくさんの人に知ってもらい、ぜひパケット仲間を増やそう!といった内容の記事です。

What is LibPGEN

LibPGEN (りぶ ぴーじぇん) は筆者(@slankdev)がパケット操作を自由に行うために開発した統合パケット操作補助のC++ライブラリです。 簡単なインターフェースで自由にパケットを操作して送受信を可能にしています。 また、既存のパケットを読み込み、ヘッダの値を変えて再度バイナリ生成、などといったことにもできます。

前提知識

今回はARPパケットを使用して遊ぶため、Ethernet, ARPの基礎知識と入門書程度のC++の知識を前提として進めていきます。

一応ARPパケットのおさらい

今回作って遊ぶARPパケットの構造とヘッダについて軽くおさらいします。必要ない人は飛ばしてもらって結構です! ARPはL3のアドレスからL2プロトコルのアドレスを求めるために使用されるプロトコルです。一般的にはIPアドレスからMACアドレスを調べるときに使いますよね。今回はこの一般例について話を進めていきます。以下にARPヘッダを示します。

   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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |            HW Type            |           Protocol            |
  +---------------+---------------+---------------+---------------+
  |     HW Len    |   Proto Len   |            Opcode             |
  +---------------+---------------+---------------+---------------+
  |                       Sender HW Address                       |
  +---------------------------------------------------------------+
  |       Sender HW Address       |     Sender Protocol Address   |
  +---------------------------------------------------------------+
  |    Sender Protocol Address    |        Target HW Address      |
  +-------------------------------+-------------------------------+
  |                        Target HW Address                      |
  +---------------------------------------------------------------+
  |                      Target Protocol Address                  |
  +---------------------------------------------------------------+

今回重要になる要素についてだけ軽く説明を行います。

要素 内容
Operation オペレーションコード. リクエストなら1,リプライなら2が入る
HW src 送信者のMACアドレス
Proto src 送信者のIPアドレス
HW dst 送信先MACアドレス, ARPリクエストなら全て0x00か0xff
Proto dst 送信先IPアドレス

まあこんな感じですね。

f:id:slankdev:20170402202541p:plain

ちなみにこれらの通信では以下のようなパケットが送られます。

ARPリクエスト

要素 内容
Operation 1 (Request)
HW src AA:AA:AA:AA:AA:AA
Proto src 192.168.0.1
HW dst ff:ff:ff:ff:ff:ff
Proto dst 192.168.0.2

ARPリプライ

要素 内容
Operation 2 (Reply)
HW src XX:XX:XX:XX:XX:XX
Proto src 192.168.0.2
HW dst AA:AA:AA:AA:AA:AA
Proto dst 192.168.0.1

これで前提知識はバッチリです!

今回のお題目

今回の目的は次の二つです。

  • パケットは簡単に作れて面白い
  • Wiresharkはすごい

パケットは簡単につくれて面白い

LibPGENはC++で簡単に様々なパケットを作成することを補助します。ではLibPGENを使ってARPパケットを作って送るプログラムを作って遊んでみましょう。

使用するプログラムを以下に示します。

#include <pgen.h>
const char* dev = "en0";

int main() {
    pgen::net_stream handle;
    handle.open(dev, pgen::open_mode::netif);

    pgen_arp pack;
    pack.ARP.operation = pgen::arp_operation::request;
    pack.ARP.hwsrc.setmacbydev(dev);
    pack.ARP.psrc.setipbydev(dev);
    pack.ARP.psrc  = "192.168.179.4";
    pack.ARP.hwdst = "ff:ff:ff:ff:ff:ff";
    pack.ARP.pdst  = "192.168.179.1";
    pack.ETH.src   = pack.ARP.hwsrc;
    pack.ETH.dst   = pack.ARP.hwdst;

    pack.compile();
    pack.summary();
    pack.hex();
    handle.send(pack.raw(), pack.length());
}

コンパイルではlibpgenをリンクしてc++11でコンパイルしてください。

g++ -std=c++11 main.cc -lpgen

これを実行すると以下のようなバイナリが生成されネットワークインターフェースから送信されます。Wiresharkでキャプチャしてみると、ちゃんとしたARPパケットがキャプチャできていることがわかります。

f:id:slankdev:20170402202608p:plain

Wiresharkはすごい

簡単にパケットは送信できてはいるのですが、これにもう一工夫すると、さらに面白いことが確認できます。今回はARPキャッシュポイズニングのパケットも作って送ってみましょう。

今作ったパケットは

要素 内容
Operation 1 (Request)
HW src 80:e6:50:::**
Proto src 192.168.179.4
HW dst ff:ff:ff:ff:ff:ff
Proto dst 192.168.179.1

返ってきたパケットは

要素 内容
Operation 2 (Reply)
HW src 00:00:00:00:00:00
Proto src 192.168.179.1
HW dst 80:e6:50:::**
Proto dst 192.168.179.4

ですが、この返信パケットを少し偽装したパケットを同時に送信してみます。具体的には以下の図のようなことをしています。

f:id:slankdev:20170402202640p:plain

別のホストから以下のようなパケットを作成して送信します。

要素 内容
Operation 2 (Reply)
HW src YY:YY:YY:YY:YY:YY
Proto src 192.168.179.1
HW dst 80:e6:50:::**
Proto dst 192.168.179.4

こうなってしまうと最初にARPリクエストを送信したホストは知りたかったIPアドレスに対応付けられているMACアドレスを知ることが出ない可能性があります、これを利用して不正に通信の向きを改ざんしたりして情報を傍受する攻撃(MITM Attack)などもあります。危険です。。。

ちなみにWiresharkでこの通信の一部始終をキャプチャしていると…

f:id:slankdev:20170402202709p:plain

すごい!すでに使われているアドレスで、変なパケットだって教えてくれる。。 ただのパケットキャプチャなのに、キャッシングしているパケットと比べて、変なパケットを調べるあたり、本当にすごい。。ってことでWiresharkはすごい! (注意, だからと言ってARPスプーフィングに対して安全という訳ではありません。)

このように簡単にパケットを作成したりすることが可能になります。LibPGENはこれだけでなく、他にも様々な機能があります。詳しくはlibpgen.orgを参照してください。