如何捕获接入点和与其连接的主机的 MAC 地址?

发布于 2024-10-09 01:33:30 字数 564 浏览 0 评论 0原文

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

在 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 );              
 }

I know that i have to use the libpcap library to capture IEEE 802.11 frames to show their MAC addresses,for example my wireless adapter is in monitor mode, and only supports "802.11 plus radiotap radio header" when i do a pcap_datalink.

In the callback function of pcap_loop what should i do to extract the MAC addresses from the packets? How i differentiate between different types of packets? Googling around doesn't me much answers,mostly on how to extract packets from wired interfaces.

 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 );              
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

格子衫的從容 2024-10-16 01:33:30

执行此操作的最佳位置是从 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稍后)。

The best place to do this is to extract the required code from the tcpdump source, which as far as I'm concerned basically is both the how-to guide for libpcap and a networking introduction all in one.

Anyway, what you need is a packet handling function as you've gathered from pcap_open_live. You will also need to create another thread or process because pcap_open_live will block the current thread whilst it works.

Now, the packet handler function looks like this:

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...
}

This will get you the mac address as a string. Be warned, however, networking isn't easy. You need to know what you're doing with binary strings of information, casting etc and you need to know what the numbers and options mean. If the tcpdump source looks complicated, it is because networking is complicated. Also, I haven't listed the headers you need to achieve this process. There are pcap tutorials out there; I suggest you take your time to read them. My simply giving you an answer won't teach you networking.

Also, this function is incomplete. You will need the appropriate allocations for the storage arrays (pcap being a C library you may want to use char* rather than string then extract back to string later).

此岸叶落 2024-10-16 01:33:30

好的,我找到了一个解决方案,基本上以下代码会跳过 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);
    }


}

Ok i found a solution, basically the following code skips past the radio header for ech packet , and get the bassid/MAC address of an access point.

Eg: my radio header has a length of 18, and it is a radiotap header, if yours is a prism/AVS header, the length would be another size.

To get a client MAC address connected to a AP, i believed you have to check the FROM DS/TO DS bits.

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);
    }


}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文