Welcome to SapporoWorks! We create stimulating network programs.
By a demand from user, SapporoWorks evolves.
トップページ| ソフトウエア| シェアウエア登録| セキュリティ情報| 開発情報| ドキュメント|
開発情報 > ドライバを使用しないパケットダンプ


概要

WinSock2.2(Windows2000 WindowsXP)以降 デバイスドライバを使用しないでもRAWソケット扱えるようになりました。

っと言うことで、早速、パケットモニタを作成してみました。
UNIXではあたりまえの事でしたが、遂にWindwosでもA4一枚のプログラムでパケットがダンプできるようになったのでした。(^^)

ws2_32.lib のリンクが必要です。

ソース
 //コンストラクタ
 __fastcall TForm1::TForm1(TComponent* Owner)
     : TForm(Owner)
 {
     //Ver2.2 でWinSockを初期化する
     WSAStartup(MAKEWORD(2,2),&wsd);
 
     hThread=NULL;
 
     //アダプタのリストをコンボボックに取得
     ListAdapter();
 }
 


 //デストラクタ
 __fastcall TForm1::~TForm1(void)
 {
     //キャプチャスレッドが走行中の場合ストップする
     if(hThread!=NULL)
         TerminateThread(hThread,ThreadId);
 
     //WinSockの終了処理
     WSACleanup();
 }
 



 //アダプタの初期化
 int __fastcall TForm1::InitAdapter(void)
 {
     char TmpBuf[1024];
     int i,max;
 	unsigned int optval;
     char buf[4096];
     DWORD d;
 
     SOCKET_ADDRESS_LIST *slist;
     SOCKADDR_IN   addr_in;
 
     //SOCKETの生成
     if( INVALID_SOCKET == (sock = WSASocket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED))){
 		wsprintf(TmpBuf,"WSASocket(AF_INET,SOCK_RAW) failed");
         Memo1->Lines->Add(TmpBuf);
         return -1;
     }
 
     //アダプタのリスト取得
     if(SOCKET_ERROR == WSAIoctl(sock,SIO_ADDRESS_LIST_QUERY,NULL,0,buf,4096,&d,NULL,NULL)){
         wsprintf(TmpBuf,"WSAIoctl(SIO_ADDRESS_LIST_QUERY) faild.");
         Memo1->Lines->Add(TmpBuf);
         return -1;
     }
     slist = (SOCKET_ADDRESS_LIST *)buf;
 
     //SOCKET のデータセット
     addr_in.sin_addr.s_addr=((SOCKADDR_IN *)slist->Address[ComboBox1->ItemIndex].lpSockaddr)->sin_addr.s_addr;
     addr_in.sin_family = AF_INET;
     addr_in.sin_port = htons(0);
 
     //bind
     if(bind(sock,(SOCKADDR *)&addr_in,sizeof(addr_in))==SOCKET_ERROR) {
         wsprintf(TmpBuf,"bind failed");
         Memo1->Lines->Add(TmpBuf);
         return -1;
     }
 
     optval=1;
     if(WSAIoctl(sock,SIO_RCVALL,&optval,sizeof(optval),NULL,0,&d,NULL,NULL)==SOCKET_ERROR){
         wsprintf(TmpBuf,"WSAIoCtl(SIO_RCVALL) failed");
         Memo1->Lines->Add(TmpBuf);
 	return -1;
     }
     return 0;
 }
 

 //キャプチャ開始・終了(キャプチャスレッドの生成・破棄)
 void __fastcall TForm1::Button1Click(TObject *Sender)
 {
 
     
     if(hThread==NULL){ //キャプチャ開始処理
         if(-1==InitAdapter())
             return;
 	//キャプチャスレッド生成
 	if(NULL!=(hThread=CreateThread(NULL,0,CaptureThread,0,0,&ThreadId)))
             Button1->Caption="Stop";
     }else{ //キャプチャ終了処理
 	//キャプチャスレッドの破棄
         TerminateThread(hThread,ThreadId);
         hThread=NULL;
         Button1->Caption="Start";
     }
 }
 




 //キャプチャスレッド本体
 unsigned long __stdcall CaptureThread(void *ArgList)
 {
 	unsigned char buf[MAX_IP_SIZE];
     WSABUF wsb;
     unsigned long len;
     DWORD Flags;
 
     while(1){
         Sleep(1);
         Application->ProcessMessages();
 
 
         wsb.buf=buf;
         wsb.len=MAX_IP_SIZE;
     	memset(wsb.buf,0x0,MAX_IP_SIZE);
         Flags=0;
 
 	//パケット取得
         if(SOCKET_ERROR==WSARecv(Form1->sock,&wsb,1,&len,&Flags,NULL,NULL)){
             wsprintf(buf,"WSARecv failed. Code %d",WSAGetLastError(),Form1->sock);
             Form1->Memo1->Lines->Add((char *)buf);
             continue;
     	}
         //パケット表示
     	Form1->Print(buf,len);
     }
 
     Form1->hThread=NULL;
     return 0;
 }
 



サンプル

サンプルプログラム実行画面


ソースファイルのダウンロード 003-src.LZH 7Kbyte 実行ファイルのダウンロード 003-bin.LZH 207Kbyte


開発者のための実装系Webマガジンへの投稿
WinPcapを使用したパケットモニターの作成方法
パケットドライバー「WinPcap」の利用方法、および取得したデータをプロトコルに従って解析する手法について紹介。
WinSock2を使用したパケットモニターの作成方法
WindowsでRAWソケットを扱う方法の紹介。GUIプログラムを作成する場合に必須となる「非ブロッキングモード」や、すべてのパケットを取得するための「プロミスキャスモード」についても触れています 。
開発情報 > ドライバを使用しないパケットダンプ

copyright(c) 1995- SapporoWorks
当サイトはリンクフリーです。リンク時に連絡などは必要有りません。また、どのページにリンクして頂いても構いません。