2

IEEE 802.11 フレームをキャプチャして MAC アドレスを表示するには、libpcap ライブラリを使用する必要があることを知っています。

pcap_loop のコールバック関数で、パケットから MAC アドレスを抽出するにはどうすればよいですか? 異なるタイプのパケットを区別するにはどうすればよいですか? グーグルで調べても、ほとんどの場合、有線インターフェイスからパケットを抽出する方法についてはあまり答えがありません。

 void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
 {
         //what should i do here?
 }

  pcap_t *handler=pcap_open_live ("wlan0", BUFSIZ,1,-1,errbuff);
 if(pcap_datalink(handler) == DLT_IEEE802_11_RADIO) 
 {
          pcap_loop(handler, -1 ,procPacket, NULL );              
 }
4

2 に答える 2

3

これを行うのに最適な場所は、必要なコードを tcpdump ソースから抽出することです。これは、基本的に libpcap のハウツー ガイドとネットワークの紹介の両方を 1 つにまとめたものです。

とにかく、必要なのは、から収集したパケット処理関数ですpcap_open_livepcap_open_live現在のスレッドが動作している間はブロックされるため、別のスレッドまたはプロセスを作成する必要もあります。

これで、パケット ハンドラー関数は次のようになります。

void packethandler( u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet )
{
    // ... allocs etc

    // these instructions convert the "packet" string
    // to a struct and determine it's type, a setting in 
    // the ethernet header.
    eptr = (struct ether_header *) packet;
    ether_type = ntohs(eptr->ether_type);

    // ...

    // these two functions extract the mac addresses 
    // into appropriately alloc'd strings.
    // ether_ntoa converts the binary representation
    // of the mac address into a string
    snprintf(ethernet_shost, 20, "%s", ether_ntoa((struct ether_addr *)eptr->ether_shost));
    snprintf(ethernet_dhost, 20, "%s", ether_ntoa((struct ether_addr *)eptr->ether_dhost));

    // carry on...
}

これにより、MACアドレスが文字列として取得されます。ただし、ネットワーキングは簡単ではないことに注意してください。情報のバイナリ文字列、キャストなどで何をしているのかを知る必要があり、数値とオプションが何を意味するのかを知る必要があります。tcpdump ソースが複雑に見える場合は、ネットワークが複雑なためです。また、このプロセスを実現するために必要なヘッダーもリストしていません。そこには pcap チュートリアルがあります。時間をかけてそれらを読むことをお勧めします。私が単に答えを出すだけでは、ネットワーキングについて学ぶことはできません。

また、この機能は不完全です。ストレージ配列に適切な割り当てが必要になります (pcap は、後で抽出して戻すchar*のではなく、使用したい C ライブラリです)。stringstring

于 2010-12-24T13:40:37.100 に答える
3

基本的に、次のコードは ech packet の無線ヘッダーをスキップし、アクセス ポイントの Bassid/MAC アドレスを取得します。

例: 私の無線ヘッダーの長さは 18 で、これは radiotap ヘッダーです。あなたがプリズム/AVS ヘッダーの場合、長さは別のサイズになります。

AP に接続されたクライアント MAC アドレスを取得するには、FROM DS/TO DS ビットを確認する必要があると思いました。

typedef struct mac_header{
unsigned char fc[2];
unsigned char id[2];
unsigned char add1[6];
unsigned char add2[6];
unsigned char add3[6];
unsigned char sc[2];
}mac_header;
typedef struct frame_control{
unsigned protocol:2;
unsigned type:2;
unsigned subtype:4;
unsigned to_ds:1;
unsigned from_ds:1;
unsigned more_frag:1;
unsigned retry:1;
unsigned pwr_mgt:1;
unsigned more_data:1;
unsigned wep:1;
unsigned order:1;
}frame_control;

typedef struct beacon_header{
unsigned char timestamp[8];

unsigned char beacon_interval[2];
unsigned char cap_info[2];
}beacon_header;

void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{

    char * temp;
    char ssid[32];    
    struct mac_header *p= (struct mac_header *)(packet+RADIOTAP_HEADER_SIZE);
    struct frame_control *control = (struct frame_control *) p->fc;
    temp = (char *) (packet + sizeof (struct mac_header) +sizeof (struct    beacon_header)+RADIOTAP_HEADER_SIZE);
    if ((control->protocol == 0) && (control->type == 0) && (control->subtype == 8) )  // beacon frame
    {        
         memset(ssid,0,32);
         memcpy (ssid, &temp[2], temp[1]);
         printf ("Destination Add : %s\n", ether_ntoa ((struct ether_addr *)p->add1));
         printf ("Source Add : %s\n", ether_ntoa ((struct ether_addr *)p->add2));
         printf ("BSSID : %s\n", ether_ntoa ((struct ether_addr *)p->add3));
         printf ("ssid = %s\n", ssid);
    }


}
于 2010-12-30T06:20:02.090 に答える