「オープンソース」を使ってみよう
(第39回 LibPGEN)
02/09
Use it ! OSS No Comments
Tweet
目次
- はじめに、パケット遊びについて
- LibPGENとは
- 紹介内容
- LibPGENでパケット遊び
- LibPGENのインストール方法
- パケットキャプチャ
- ARPパケットを送信してIPアドレスからMACアドレスを調べるプログラム
- make
- clang (なければg++)
- ar
- git
はじめに、パケット遊びについて
現在パケットを解析といえば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でパケット遊び
インストール
ここではLibPGENのインストール方法を紹介します。簡単で数分で終わります。
実行可能環境
version1.0ではLinux、BSDをサポートしています。とても古くない限り動くはずです。
必要なパッケージ
コンパイルでは以下のパッケージを使用します。
インストール方法
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の売りの一つでもあります。
公式サイトではこれだけでなく様々なドキュメントも公開しています。
使用するときはぜひ見てください。
参考情報
- LibPGENについて
- 今回紹介したプログラムについて