2011-11-20 2 views
2

나는 pcap 및 무선으로 프로젝트를 수행하고 있습니다. 예를 들어 내 이전 질문에 대한 oe에 대한 응답으로 무선 프레임에서 mac 주소를 추출하려고합니다. 나는 radiotap 헤더와 기본 관리 프레임을위한 구조를 만들었다. 어떤 이유로 Mac 주소를 출력하려고 할 때 잘못된 데이터가 출력됩니다. 내가 wireshark와 비교할 때 나는 왜 무선 탭 데이터가 올바르게 인쇄되고 있는지는 모르지만 MAC 주소는 그렇지 않다. wireshark가 패킷을보고 캡처 한 패킷을 비교할 때 표시되는 16 진 덤프에 추가로 패딩이 표시되지 않습니다. 나는 C와 약간 famialar이지만 전문가가 아니므로 포인터와 구조를 제대로 사용하지 않아서 누군가 내가 잘못한 것을 보여줄 수 있습니까?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'를'0'보다는'6'으로 재설정하는 것이 도움이 될 수 있습니다. 그러나 이것이 유일한 문제인지는 모르겠습니다. "잘못된 데이터 "매우 구체적인 것은 아니다. 예제 패킷 16 진 덤프와 해당 "잘못된"출력이 유용 할 것입니다. –

+0

의견을 주셔서 감사합니다 – dudebrobro

답변

8

당신은 잘못 몇 가지 일을하고 있습니다.

당신이 잘못하고있는 it_version, it_pad, it_lenit_present보다 더 많은 필드가있는 구조로 radiotap 헤더를 선언되는 첫번째 것. 임의의 radiotap 헤더에서, 예를 들어, 필드 다음의 64 비트 MAC_timestamp 필드가있을 것이라는 보장은 없습니다. it_present 필드를보고 헤더의 어떤 필드가 실제로 나타나는지 확인해야합니다. 라디오 타일 헤더를 처리하는 방법에 대한 자세한 내용은 the radiotap Web site을 참조하십시오. 0 (또는 NULL)에 대한 필드의 값을 비교

하지 작업을 수행 - 필드가 존재하지 않으면, 단순히 존재하지 않는다.

특정 OS의 특정 네트워킹 어댑터에 대해 특정 버전의 드라이버에서 코드가 작동하지만 드라이버가 변경되거나 다른 종류의 어댑터 (예 : Atheros Broadcom 어댑터 대 Mac) 또는 다른 운영 체제 (예 : Linux)에서이 어댑터를 실행하려는 경우

이 코드가 빅 엔디안 시스템에서 실행되기를 기대하는 경우 모든 리틀 엔디안이므로 라디오 태그 헤더의 필드를 더 조심스럽게 가져와야합니다. (코드에 #define가 충분 하지입니다.) 당신이 파워 맥에서 실행하는 경우에만 맥에 표시 할 바이트 순서 문제를 제외하고

, 당신은 제대로 있습니다 radiotap 헤더를 건너 뛰어서 문제가되지 않습니다.

또한 MAC 타임 스탬프는 64 비트 정수이며, 32 비트 컴퓨터에서는 %u 대신 %llu으로 인쇄해야합니다.

오류가 있는지 확인해야합니다. 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->caplen 를 확인해야합니다 pkthdr->len을 확인 루프를 의미

[0] 또는 rh->it_lenpkthdr->caplen 동안보다 크거나 같은 있는지 확인하기 위해 점검해야으로 (pkthdr->caplen에서 rh->it_len을 빼야한다 또는 radiotap 헤더를 파싱하기 전에, 그 뺄셈의 결과는 양의 값을가집니다). 스냅 샷 길이는 모두 의사 머리글 (예 : radiotap 헤더)을 포함합니다.

+0

고마워요. 대부분의 코드는 게시하기 전에 정리해야한다는 것은 정말 나쁘지만 두 가지 질문에 대한 모든 조언에 감사드립니다. 당신이 나를 위해 대답했다는 것을 정리하고 당신이 준 힌트를 가지고 일을 얻으려고 노력합니다. 다시 한 번 감사드립니다. – dudebrobro