2011-11-20 54 views
2

我正在使用pcap和無線方式處理項目。根據我之前提出的問題發佈的示例,我嘗試從無線幀中提取MAC地址。我已經爲radiotap頭文件和基本管理框架創建了結構。出於某種原因,當試圖輸出MAC地址時,我正在輸出錯誤的數據。當我比較Wireshark時,我不明白爲什麼無線電竊聽數據正確輸出,但是MAC地址不是。當我查看數據包並比較我捕獲的數據包時,在Wireshark顯示的十六進制轉儲中沒有看到任何附加填充。我有點兒有c,但不是專家,所以也許我沒有正確使用指針和結構,有人可以幫我看看我做錯了什麼?使用pcap處理來自802.11幀的不正確mac地址

感謝, 昆汀

// 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; 
} 
+0

我沒有爲Mac編碼,並且通常在查找相關行時遇到了一些問題。但是我最近在pcap上發佈了一個問題,得到了一個答案,在2.下,可能會有一些適用於您的問題。也許看看。 – gnometorule

+1

打印'fr-> wi_add2'和'fr-> wi_add3'之前將'k'重置爲'6'而不是'0'可能會有所幫助,但我不知道這是否是唯一的問題,因爲「打印出錯誤的數據「不是很具體。示例數據包十六進制轉儲和相應的「錯誤」輸出將很有用。 –

+0

感謝您的意見 – dudebrobro

回答

8

你做的幾件事情是錯誤的。

你做錯了,是聲明radiotap頭與比it_versionit_padit_lenit_present多個字段結構的第一事情。有絕對不能保證,在任意無線電標頭中,例如,在it_present字段之後將有一個64位MAC_timestamp字段。您必須查看it_present字段以查看標題中的哪些字段實際存在。有關如何處理無線電標頭的詳細信息,請參閱the radiotap Web site

字段的值對0(或NULL)比較確實工作 - 如果字段不存在,它僅僅不存在

您的代碼可能碰巧適用於特定OS上的特定網絡適配器的特定驅動程序版本,但如果驅動程序發生更改或者在具有不同類型適配器的計算機上運行,​​它可能會失敗(例如,Atheros與Mac上的Broadcom適配器)或者如果您嘗試在不同的操作系統(例如Linux)上運行此操作系統。

如果您希望此代碼在大端機上運行,​​您還需要更仔細地從radiotap頭獲取字段,因爲它們都是小端。 (在你的代碼的#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個字節」; radiotap頭可能比這更長,所以你甚至不會獲得所有的radiotap頭,更不用說獲得任何802.11頭。

如果要捕獲整個數據包,只需將pcap_set_snaplen()呼叫離開。

呵呵,如果你想成爲真的請小心,當你在看無線傳感器和802.11標頭時,你還沒有過去pkthdr->caplen

這也意味着你的循環,檢查pkthdr->len應該檢查pkthdr->caplen應利用包開始[0]還是應該從pkthdr->caplen減去rh->it_len(你應該檢查,以確保rh->it_len大於或等於pkthdr->caplen而或者在你解析radiotap頭之前,這個減法的結果將是正的)。快照長度包括全部僞報頭,例如無線電報頭。

+0

謝謝。大多數代碼非常糟糕,我應該在發佈前清理它,但是要感謝所有關於這兩個問題的建議。你回答我,我會清理一些東西,並採取你給的提示,並試圖讓事情工作。再次感謝 – dudebrobro