我知道我必须使用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 );
}
答案 0 :(得分: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
。
答案 1 :(得分:3)
好的,我找到了一个解决方案,基本上下面的代码跳过了ech数据包的无线电报头,并获得了接入点的低音/ 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);
}
}