2

我知道我必须使用 libpcap 库来捕获 IEEE 802.11 帧以显示它们的 MAC 地址,例如我的无线适配器处于监控模式,并且在我执行 pcap_datalink 时仅支持“802.11 plus radiotap radio header”。

在 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 的操作指南和网络介绍合二为一。

无论如何,您需要的是从pcap_open_live. 您还需要创建另一个线程或进程,因为pcap_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 是您可能想要使用的 C 库,char*而不是稍后string再提取string)。

于 2010-12-24T13:40:37.100 回答
3

好的,我找到了一个解决方案,基本上以下代码跳过了 ech 数据包的无线电标头,并获取了接入点的 bassid/MAC 地址。

例如:我的无线电报头长度为 18,它是一个 radiotap 报头,如果你的是 prism/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 回答