我正在做一个关于pcap和无线的项目。按照我之前问题的一个例子,我正在尝试从无线帧中提取mac地址。我已经创建了无线窃听报头和基本管理框架的结构。由于某些原因,当我尝试输出mac地址时,我打印出了错误的数据。当我与wireshark进行比较时,我不明白为什么无线电窃听数据可以正确打印出来,而mac地址却不能。当我查看数据包并比较我捕获的数据包时,我在wireshark显示的十六进制转储中没有看到任何额外的填充。我对c比较熟悉,但不是专家,所以可能我没有正确地使用指针和结构,有人能帮我指出我做错了什么吗?
谢谢,昆汀
// main.c
// MacSniffer
//
#include <pcap.h>
#include <string.h>
#include <stdlib.h>
#define MAXBYTES2CAPTURE 65535
#ifdef WORDS_BIGENDIAN
typedef struct frame_control
{
unsigned int subtype:4; /*frame subtype field*/
unsigned int protoVer:2; /*frame type field*/
unsigned int version:2; /*protocol version*/
unsigned int order:1;
unsigned int protected:1;
unsigned int moreDate:1;
unsigned int power_management:1;
unsigned int retry:1;
unsigned int moreFrag:1;
unsigned int fromDS:1;
unsigned int toDS:1;
}frame_control;
struct ieee80211_radiotap_header{
u_int8_t it_version;
u_int8_t it_pad;
u_int16_t it_len;
u_int32_t it_present;
u_int64_t MAC_timestamp;
u_int8_t flags;
u_int8_t dataRate;
u_int16_t channelfrequency;
u_int16_t channFreq_pad;
u_int16_t channelType;
u_int16_t channType_pad;
u_int8_t ssiSignal;
u_int8_t ssiNoise;
u_int8_t antenna;
};
#else
typedef struct frame_control
{
unsigned int protoVer:2; /* protocol version*/
unsigned int type:2; /*frame type field (Management,Control,Data)*/
unsigned int subtype:4; /* frame subtype*/
unsigned int toDS:1; /* frame coming from Distribution system */
unsigned int fromDS:1; /*frame coming from Distribution system */
unsigned int moreFrag:1; /* More fragments?*/
unsigned int retry:1; /*was this frame retransmitted*/
unsigned int powMgt:1; /*Power Management*/
unsigned int moreDate:1; /*More Date*/
unsigned int protectedData:1; /*Protected Data*/
unsigned int order:1; /*Order*/
}frame_control;
struct ieee80211_radiotap_header{
u_int8_t it_version;
u_int8_t it_pad;
u_int16_t it_len;
u_int32_t it_present;
u_int64_t MAC_timestamp;
u_int8_t flags;
u_int8_t dataRate;
u_int16_t channelfrequency;
u_int16_t channelType;
int ssiSignal:8;
int ssiNoise:8;
};
#endif
struct wi_frame {
u_int16_t fc;
u_int16_t wi_duration;
u_int8_t wi_add1[6];
u_int8_t wi_add2[6];
u_int8_t wi_add3[6];
u_int16_t wi_sequenceControl;
// u_int8_t wi_add4[6];
//unsigned int qosControl:2;
//unsigned int frameBody[23124];
};
void processPacket(u_char *arg, const struct pcap_pkthdr* pkthdr, const u_char* packet)
{
int i= 0, *counter = (int *) arg;
struct ieee80211_radiotap_header *rh =(struct ieee80211_radiotap_header *)packet;
struct wi_frame *fr= (struct wi_frame *)(packet + rh->it_len);
u_char *ptr;
//printf("Frame Type: %d",fr->wi_fC->type);
printf("Packet count: %d\n", ++(*counter));
printf("Received Packet Size: %d\n", pkthdr->len);
if(rh->it_version != NULL)
{
printf("Radiotap Version: %d\n",rh->it_version);
}
if(rh->it_pad!=NULL)
{
printf("Radiotap Pad: %d\n",rh->it_pad);
}
if(rh->it_len != NULL)
{
printf("Radiotap Length: %d\n",rh->it_len);
}
if(rh->it_present != NULL)
{
printf("Radiotap Present: %c\n",rh->it_present);
}
if(rh->MAC_timestamp != NULL)
{
printf("Radiotap Timestamp: %u\n",rh->MAC_timestamp);
}
if(rh->dataRate != NULL)
{
printf("Radiotap Data Rate: %u\n",rh->dataRate);
}
if(rh->channelfrequency != NULL)
{
printf("Radiotap Channel Freq: %u\n",rh->channelfrequency);
}
if(rh->channelType != NULL)
{
printf("Radiotap Channel Type: %06x\n",rh->channelType);
}
if(rh->ssiSignal != NULL)
{
printf("Radiotap SSI signal: %d\n",rh->ssiSignal);
}
if(rh->ssiNoise != NULL)
{
printf("Radiotap SSI Noise: %d\n",rh->ssiNoise);
}
ptr = fr->wi_add1;
int k= 6;
printf("Destination Address:");
do{
printf("%s%X",(k==6)?" ":":",*ptr++);
}
while(--k>0);
printf("\n");
ptr = fr->wi_add2;
k=0;
printf("Source Address:");
do{
printf("%s%X",(k==6)?" ":":",*ptr++);
}while(--k>0);
printf("\n");
ptr = fr->wi_add3;
k=0;
do{
printf("%s%X",(k==6)?" ":":",*ptr++);
}
while(--k>0);
printf("\n");
/* for(int j = 0; j < 23124;j++)
{
if(fr->frameBody[j]!= NULL)
{
printf("%x",fr->frameBody[j]);
}
}
*/
for (i = 0;i<pkthdr->len;i++)
{
if(isprint(packet[i +rh->it_len]))
{
printf("%c",packet[i + rh->it_len]);
}
else{printf(".");}
//print newline after each section of the packet
if((i%16 ==0 && i!=0) ||(i==pkthdr->len-1))
{
printf("\n");
}
}
return;
}
int main(int argc, char** argv)
{
int count = 0;
pcap_t* descr = NULL;
char errbuf[PCAP_ERRBUF_SIZE], *device = NULL;
struct bpf_program fp;
char filter[]="wlan broadcast";
const u_char* packet;
memset(errbuf,0,PCAP_ERRBUF_SIZE);
device = argv[1];
if(device == NULL)
{
fprintf(stdout,"Supply a device name ");
}
descr = pcap_create(device,errbuf);
pcap_set_rfmon(descr,1);
pcap_set_promisc(descr,1);
pcap_set_snaplen(descr,30);
pcap_set_timeout(descr,10000);
pcap_activate(descr);
int dl =pcap_datalink(descr);
printf("The Data Link type is %s",pcap_datalink_val_to_name(dl));
//pcap_dispatch(descr,MAXBYTES2CAPTURE,1,512,errbuf);
//Open device in promiscuous mode
//descr = pcap_open_live(device,MAXBYTES2CAPTURE,1,512,errbuf);
/* if(pcap_compile(descr,&fp,filter,0,PCAP_NETMASK_UNKNOWN)==-1)
{
fprintf(stderr,"Error compiling filter\n");
exit(1);
}
if(pcap_setfilter(descr,&fp)==-1)
{
fprintf(stderr,"Error setting filter\n");
exit(1);
}
*/
pcap_loop(descr,0, processPacket, (u_char *) &count);
return 0;
}发布于 2011-11-21 07:43:37
你做错了几件事。
您要做的第一件事就是将无线窃听报头声明为一个比it_version、it_pad、it_len和it_present更多字段的结构。绝对不能保证在任意无线电分接报头中,例如,在it_present字段之后将存在64位MAC_timestamp字段。您必须查看it_present字段,以查看报头中的哪些字段实际存在。有关如何处理无线窃听报头的详细信息,请参阅the radiotap Web site。
将字段的值与0(或NULL)进行比较是行不通的--如果字段不存在,那么它就不存在。
您的代码可能碰巧与特定OSes上的特定网络适配器的特定版本的驱动程序一起工作,但如果更改了驱动程序,或者如果您在具有不同类型适配器的计算机上运行(例如,Mac上的Atheros与Broadcom适配器),或者如果您尝试在不同的操作系统(例如,Linux)上运行此程序,则代码可能会失败。
如果您希望这段代码在大端计算机上运行,那么您还需要更加小心地从无线窃听报头中获取字段,因为它们都是小端的。(代码中的#define不足以做到这一点。)
除了字节顺序问题,只有当你在PowerPC Mac上运行时,它才会出现在Mac上,你正确地跳过了无线窃听报头,所以这不是问题所在。
而且,MAC时间戳是一个64位整数,在32位机器上,它必须使用%llu而不是%u打印。
您还应该检查错误。如果看到数据包,pcap_create()和pcap_activate()大概不会失败,所以这可能不是直接的问题,但无论如何都应该检查失败。pcap_set_例程可能也不会失败,至少在Wi-Fi设备上不会失败,但无论如何都应该检查一下。
如果你要假设包是802.11+radiotap包,你可能至少应该检查一下,以确保pcap_datalink()的返回值是DLT_IEEE802_11_RADIO,如果不是,则失败。在此过程中,在为链路层类型打印的消息末尾添加一个换行符。
但是你主要认为你做错了,那就是捕获每个包不超过30个字节!当您执行pcap_set_snaplen(descr,30);时,您说的是“不要捕获任何超过30个字节的内容”;无线窃听报头可能比这个更长,所以您甚至无法获取所有的无线窃听报头,更不用说获取802.11个报头中的任何一个了。
如果您想捕获整个数据包,只需省略pcap_set_snaplen()调用。
哦,如果你真的想要小心,当你看着无线窃听器和802.11报头时,请确保你没有超过pkthdr->caplen。
这也意味着检查pkthdr->len的循环应该检查pkthdr->caplen,并且应该以packet开头,或者应该从pkthdr->caplen中减去rh->it_len (因为您应该检查以确保rh->it_len大于或等于pkthdr->caplen,而在您解析radiotap报头时或之前,减法的结果将是肯定的)。快照长度包括所有伪报头,例如无线分接报头。
https://stackoverflow.com/questions/8203419
复制相似问题