「オープンソース」を使ってみよう
(第39回 LibPGEN)

No Comments
このエントリーをはてなブックマークに追加

目次

  • はじめに、パケット遊びについて
  • LibPGENとは
  • 紹介内容
  • LibPGENでパケット遊び
  • はじめに、パケット遊びについて

    現在パケットを解析といえばWiresharkを使った解析が大本命。
    ほぼ全ての作業をこれ一つでできてしまうとてもクールなツールで、
    私も大好きです。ですが、パケットを見るだけではパケットの全てを
    理解したとは言えないと私は考えます。
    自分でパケットを作って、いじって、送って、受け取って、いろいろな
    面からパケットで遊ぶことで楽しみながらネットワークの勉強につながる
    ことができると考えます。
    私はこれを「パケット遊び」と勝手に名付けて親しんでいます。

    pcapファイルなどから新たにパケットを送信したり、パケットを改変したりする
    ツールは幾つかありますが、プログラミング言語からパケットを操るツールは
    そこまで多くはありません。ここでは私の開発している統合パケット解析を助ける
    C++のライブラリ「LibPGEN」のご紹介をさせていただきます。

    LibPGENを使った簡単なサンプルプログラムを紹介します。
    プログラムの詳細な解説やLibPGENについての詳しい情報は公式サイトの
    リンクを貼っておくのでそちらを参照してください。

    LibPGENとは

    LibPGENとは私が開発しているC++でのパケット解析を助けるライブラリです。
    もともとLibrary Packer GENeratorとしてパケットを生成するライブラリだった
    のですが、いろいろ機能を追加した結果、統合パケット解析ライブラリとなりました。
    2016年2月1日現在、Version1.0が最新安定版です。

    公式ドキュメント

    公式サイト
    http://libpgen.org

    開発者ブログ
    http://blog.slankdev.net

    どのような方が対象のソフトウェアか

    ネットワークやパケットの勉強を考えている方や、パケットを愛する全ての皆様。
    C言語の基本文法とTCP/IPの基本的な知識がある方を対象にしています。

    実行可能環境

    言語: C++
    OS : Linux, BSDで動作します。
    BSDに関してはOSXでしか動作確認を行っていないので、今後確認をしていきます。

    紹介内容

    今回紹介する内容はこちらです。

    • LibPGENのインストール方法
    • パケットキャプチャ
    • ARPパケットを送信してIPアドレスからMACアドレスを調べるプログラム

    また、今回紹介する内容は私のブログでも一部詳細に紹介しているので
    もしよければそちらも参照してください。

    LibPGENでパケット遊び

    インストール

    ここではLibPGENのインストール方法を紹介します。簡単で数分で終わります。

    実行可能環境

    version1.0ではLinux、BSDをサポートしています。とても古くない限り動くはずです。

    必要なパッケージ

    コンパイルでは以下のパッケージを使用します。

    • make
    • clang (なければg++)
    • ar
    • git

    インストール方法

    GitHubでソースコードを公開しているので、最新版をpullしてインストールします。

    $ git clone https://github.com/slankdev/libpgen.git
    $ cd libpgen 
    $ make 
    $ sudo make install 

    これでインストールが完了です。
    あとはC++のプログラムを作ってpgen.hをインクルードして、
    コンパイル時はlibpgenをリンクしてください。
    それだけでLibPGENの全ての機能を使うことができます。

    パケットを観る

    今回はLibPGENを使用して簡単なパケットキャプチャを作って、
    パケットを見て行こうと思います。

    ソースコード

    パケットをネットワークインターフェースから受信して
    それを簡易表示するプログラムを示します。
    今回はICMPパケットのみをキャプチャしてみることにしましょう。

    
    #include <pgen.h>
    
    
    int main(int argc, char** argv){
    	if(argc < 2){
    		printf("usage: %s interface \n", argv[0]);
    		return -1;
    	}
    
    	pgen_t* handle = pgen_open(argv[1], NULL);
    	if(handle == NULL){
    		pgen_perror("pgen_open");
    		return -1;
    	}
    
    	u_char buf[10000];
    	int buflen;
    	while(1) {
    		buflen = pgen_recv(handle, buf, sizeof(buf));
    		pgen_unknown packet(buf, buflen);
    		if(packet.isICMP()){ 
    			packet.summary();
    			packet.hex();
    		}
    	}
    
    	pgen_close(handle);
    	return 0;
    }
    

    実行

    早速プログラムを実行してパケットを見てみましょう。
    libpgenを使ってコンパイルするためオプションで -lpgen を指定します。
    LibPGENはRaw SocketやBPFを使用しているため実行はRoot権限で行ってください。
    今回はOSX10.10.5で実行しました。

    実行すると以下のようにICMPパケットをキャプチャすることができます。

    
    [slank@localhost]$ g++ capture.cc -lpgen
    [slank@localhost]$ sudo ./a.out en0
    hexdump len: 98
    0000:    80 e6 50 17 18 46 a2 12  42 17 d8 8f 08 00 45 00   ..P..F..  B.....E.
    0010:    00 54 f5 72 00 00 31 01  f4 34 ad c2 7e 91 c0 a8   .T.r..1.  .4..~...
    0020:    b3 05 00 00 3f 7c 88 df  00 01 56 a9 bd 84 00 0c   ....?|..  ..V.....
    0030:    38 66 08 09 0a 0b 0c 0d  0e 0f 10 11 12 13 14 15   8f......  ........
    0040:    16 17 18 19 1a 1b 1c 1d  1e 1f 20 21 22 23 24 25   ........  .. !"#$%
    0050:    26 27 28 29 2a 2b 2c 2d  2e 2f 30 31 32 33 34 35   &'()*+,-  ./012345
    0060:    36 37                                              67
    unknown(packet=[ICMP|IP|ETH]  192.168.179.5 > 173.194.126.145  len=98
    hexdump len: 98
    0000:    a2 12 42 17 d8 8f 80 e6  50 17 18 46 08 00 45 00   ..B.....  P..F..E.
    0010:    00 54 ba 55 00 00 40 01  20 52 c0 a8 b3 05 ad c2   .T.U..@.   R......
    0020:    7e 91 08 00 2f a0 88 df  00 02 56 a9 bd 85 00 0c   ~.../...  ..V.....
    0030:    40 40 08 09 0a 0b 0c 0d  0e 0f 10 11 12 13 14 15   @@......  ........
    0040:    16 17 18 19 1a 1b 1c 1d  1e 1f 20 21 22 23 24 25   ........  .. !"#$%
    0050:    26 27 28 29 2a 2b 2c 2d  2e 2f 30 31 32 33 34 35   &'()*+,-  ./012345
    0060:    36 37                                              67
    unknown(packet=[ICMP|IP|ETH]  173.194.126.145 > 192.168.179.5  len=98
    hexdump len: 98
    0000:    80 e6 50 17 18 46 a2 12  42 17 d8 8f 08 00 45 00   ..P..F..  B.....E.
    0010:    00 54 f8 05 00 00 31 01  f1 a1 ad c2 7e 91 c0 a8   .T....1.  ....~...
    0020:    b3 05 00 00 37 a0 88 df  00 02 56 a9 bd 85 00 0c   ....7...  ..V.....
    0030:    40 40 08 09 0a 0b 0c 0d  0e 0f 10 11 12 13 14 15   @@......  ........
    0040:    16 17 18 19 1a 1b 1c 1d  1e 1f 20 21 22 23 24 25   ........  .. !"#$%
    0050:    26 27 28 29 2a 2b 2c 2d  2e 2f 30 31 32 33 34 35   &'()*+,-  ./012345
    0060:    36 37                                              67
    

    とても簡単なプログラムでパケットキャプチャが作成できます。

    パケットを造る

    パケットを見ることができたので、次はパケットを自分で作って送ってみましょう。
    Ethernetネットワークで重要な役割をしているARPのパケットを送信するプログラムを
    示します。192.168.0.1のMACアドレスを調べるプログラムを示します。

    ソースコード

    
    #include >pgen.h<
    
    int main(int argc, char** argv){
    	if(argc < 3){
    		printf"usage: %s interface targetIP \n" argv[0]);
    		return -1;
    	}
    
    	pgen_t* handle = pgen_open(argv[1], NULL);
    	if(handle == NULL){
    		pgen_perror"pgen_open"
    		return -1;
    	}
    
    	pgen_arp packet;
    	packet.ETH.src.setmacbydev(argv[1]);
    	packet.ETH.dst = "ff:ff:ff:ff:ff:ff"
    	packet.ETH.type = 0x0806;
    	packet.ARP.operation = 1;
    	packet.ARP.hwsrc = packet.ETH.src;
    	packet.ARP.psrc.setipbydev(argv[1]);
    	packet.ARP.hwdst = packet.ETH.dst;
    	packet.ARP.pdst = argv[2];
    	packet.send(handle);
    
    	while(1){
    		u_char buffer[10000];
    		int buflen = pgen_recv(handle, buffer, sizeof(buffer));
    		pgen_unknown buf(buffer, buflen);
    		if(buf.isARP()){
    			packet.cast(buffer, buflen);
    			if(packet.ARP.operation == 2){ 
    				packet.summary();
    				break;
    			}
    		}
    	}
    
    	pgen_close(handle);
    	return 0;
    }
    

    実行

    では実行してIPアドレスからMACアドレスを調べてみましょう。

    
    $ g++ arp.cc -lpgen
    $ sudo ./a.out eth0 192.168.0.1
    ARP { 192.168.179.1 is at a2:12:42:**:**:** }
    

    無事MACアドレスを調べることができました。

    まとめ

    このようにLibPGENではパケットを簡単に作成、解析、送受信をすることができます。
    今回紹介した機能だけでなく他にも様々機能を持ち、今後も追加予定です。

    今回紹介はできませんでしたが、Pcapファイルの読み書きやPcapNgファイルの
    読み書きもサポートしています。キャプチャしたパケットを保存することなども
    簡単に行えます。PcapNgファイルはWiresharkのデフォルトのキャプチャ形式で
    ありながら、様々なツールに対応していないので、PcapNgファイルの読み書き
    対応はLibPGENの売りの一つでもあります。

    公式サイトではこれだけでなく様々なドキュメントも公開しています。
    使用するときはぜひ見てください。

    参考情報

Comments are closed.