2014-11-16 3 views
1

Я пытаюсь улучшить свои знания в области C/сети, реализуя инструмент спуфинга ARP с помощью библиотеки Pcap.C/PCAP: все значения пакета ARP 0

Я застрял в обнюхивающих пакетах arp. Я могу определить тип ARP в поле ethertype фрейма Ethernet. Но когда я «читаю» пакет ARP, все значения равны 0 (null), но аппаратный адр (MAC) & адрес протокола (ip) очень странный 8-байтовый номер, повторенный (например, 20e54ef12: 20e54ef12: 20e54ef12 ...). Я просто не могу понять. Вот что я сделал до сих пор:

packet_struct.h (различные структуры, используемые для ETH, АРП, IP ...)

#ifndef DEF_PACKET_STRUCT 
#define DEF_PACKET_STRUCT 
#include <sys/types.h> 
#define BUFF_SIZE 1518 
#define ETH_SIZE 14 
#define ARP_SIZE 28 
/* in bytes */ 
#define ETH_ADDR_SIZE 6 
#define IP_ADDR_SIZE 4 

typedef struct pkt_eth { 
    unsigned char dest[ETH_ADDR_SIZE]; 
    unsigned char src[ETH_ADDR_SIZE]; 
    unsigned short type; 
} pkt_eth; 

#define ETHERTYPE_ARP 0x0806 
#define ARP_REQUEST 1 
#define ARP_REPLY 2 
typedef struct pkt_arp { 
    unsigned short htype;/* hardware type => ethernet , etc */ 
    unsigned short ptype; /*protocol type => ipv4 or ipv6 */ 
    unsigned char hard_addr_len; /* usually 6 bytes for ethernet */ 
    unsigned char proto_addr_len; /*usually 8 bytes for ipv4 */ 
    unsigned short opcode; /* type of arp */ 
    unsigned char hard_addr_send[ETH_ADDR_SIZE]; 
    unsigned char proto_addr_send[IP_ADDR_SIZE]; 
    unsigned char hard_addr_dest[ETH_ADDR_SIZE]; 
    unsigned char proto_addr_dest[IP_ADDR_SIZE]; 
} pkt_arp; 

#define ETHERTYPE_IP 0x0800 
typedef struct pkt_ip { 
    unsigned char vhl; 
    unsigned char tos; 
    unsigned short len; 
    unsigned short id; 
    unsigned short off; 
    unsigned char ttl; 
    unsigned char proto; 
    unsigned short crc; 
    unsigned int addr_src; 
    unsigned int addr_dest; 
} pkt_ip; 

#endif 

packet_print.c (утилиты для информационный пакет печати)

#include "packet_struct.h" 
#include <stdio.h> 
#include <stdlib.h> 

char * to_addr(unsigned char * addr, int length) { 
    int i = 0; 
    char string[length]; 
    for(i=0; i< length; i++) 
     sprintf(string,"%02x:",addr[i]); 
    return string; 
} 
void print_pkt_eth(pkt_eth * eth) { 
    int i = 0; 

    fprintf(stdout,"Ethernet Layer \n"); 
    fprintf(stdout,"\tSource:\t"); 
    for(i=0;i<ETH_ADDR_SIZE;i++) 
     fprintf(stdout,"%02x:",eth->src[i]); 
    //fprintf(stdout,"%s",to_addr(eth->src,ETH_ADDR_SIZE)); 
    fprintf(stdout,"\n\tDest:\t"); 
    for(i=0;i<ETH_ADDR_SIZE;i++) 
     fprintf(stdout,"%02X:",eth->dest[i]); 

    if(ntohs(eth->type) == ETHERTYPE_IP) 
     fprintf(stdout,"\n\tType:\t IPv4"); 
    else if(ntohs(eth->type) == ETHERTYPE_ARP) 
     fprintf(stdout,"\n\tType:\t ARP"); 
    printf("\n"); 
} 

void print_pkt_arp(pkt_arp * arp) { 
    int op = 0; 
    int i = 0; 
    printf("ARP Layer \n"); 
     printf("\tHardware type:\t%02d\n",arp->htype); 
     printf("\tProtocol type:\t%02d\n",arp->ptype); 
     printf("\tHardware addresses length:\t%01d\n",arp->hard_addr_len); 
     printf("\tProtocol addresses length:\t%01d\n",arp->proto_addr_len); 
     op = ntohs(arp->opcode); 
     printf("\tOperation code:\t%01u\n",op); 
     printf("\tHardware sender:\t"); 
     for(i=0;i<ETH_ADDR_SIZE;i++) 
      printf("%02x:",arp->hard_addr_send); 
     printf("\n\tSoftware sender:\t"); 
     for(i=0;i<IP_ADDR_SIZE;i++) 
      printf("%02x:",arp->proto_addr_send); 
     printf("\n"); 

} 

void print_pkt_ip(pkt_ip * ip) { 
} 

sniffer.c (сам инструмент)

#include<stdio.h> 
#include<stdlib.h> 
#include<netinet/in.h> // for addresses translation 
#include<errno.h> 

// for ntohs etc 
// can also be necessary to include netinet/in 
#include <arpa/inet.h> 

#include "packet_struct.h" 

#include <pcap.h> 

#define SNAP_LEN 1518 
int packet_count = 0; 
void handleARP(const struct pkt_eth * eth) { 

    const struct pkt_arp * arp = (const struct pkt_arp *) (eth + ETH_SIZE); 
    print_pkt_arp(arp); 
    if(ntohs(arp->htype) != 1) { 
     fprintf(stderr, "Error : ARP packet does not contain a Hardware type Ethernet -> %d\n",ntohs(arp->htype)); 
     return; 
    } 

    // check protocol type 
    if(ntohs(arp->ptype) != 0x800) { 
     fprintf(stderr,"Error : ARP packet does not contain a IPv4 type\n"); 
     return; 
    } 

} 

void sniff_callback(u_char * user, const struct pcap_pkthdr * h,const u_char * bytes) { 
    int i = 0; 
    for(i=0; i < 25; i++) { printf("-"); }; printf("\n"); 
    printf("Received packet number %d ==> %d\n",packet_count++,h->len); 
    const struct pkt_eth * eth; 
    unsigned short eth_type; 

    unsigned int captureLength = h->caplen; 
    unsigned int packetLength = h->len; 

    if(captureLength != packetLength) { 
     fprintf(stderr,"Error : received packet with %d available instead of %d \n",captureLength,packetLength); 
     return; 
    } 
    if(captureLength < ETH_SIZE) { 
     fprintf(stderr,"Error : received too small packet , %d bytes",captureLength); 
     return; 
    } 

    eth = (struct pkt_eth*)(bytes); 

    // print the packet 
    print_pkt_eth(eth); 

    eth_type = ntohs(eth->type); 

    if(eth_type == ETHERTYPE_ARP) { 
     handleARP(eth); 
    } 

    for(i=0; i < 25; i++) { printf("-"); }; printf("\n"); 
    return; 

} 

/* returns 0 if everything went well */ 
int set_options(pcap_t * handle) { 
    int ret = 0; 

    ret = pcap_set_promisc(handle,1); 
    if(ret != 0) { 
     fprintf(stderr,"Error setting promiscuous mode\n"); 
     return ret; 
    } 
    ret = pcap_set_snaplen(handle,SNAP_LEN); 
    if(ret != 0) { 
     fprintf(stderr,"Error setting snapshot length\n"); 
     return ret; 
    } 
    ret = pcap_set_timeout(handle,1000); 
    if(ret != 0) { 
     fprintf(stderr,"Error setting timeout\n"); 
     return ret; 
    } 

    return ret; 
} 
int activate(pcap_t * handle) { 
    int ret = pcap_activate(handle); 
    switch(ret) { 
     case 0: 
      fprintf(stdout,"Activation complete\n"); 
      break; 
     case PCAP_WARNING_PROMISC_NOTSUP: 
       fprintf(stderr,"Promiscuous mode not supported\n"); 
        return ret; 
     case PCAP_ERROR_PERM_DENIED: 
       fprintf(stderr,"Not have the permission required\n"); 
       return ret; 
     case PCAP_ERROR_PROMISC_PERM_DENIED: 
       fprintf(stderr,"Not have the permission required for promiscuous\n"); 
       return ret; 
     default: 
       fprintf(stderr,"Error occured during activation, see code\n"); 
       return ret; 
    } 
    return ret; 
} 


/* Will activate device , filter & call the sniffing loop */ 
int sniffing_method(char * interface, char * filter,int packet_count) { 

    char err[PCAP_ERRBUF_SIZE]; //error buffer 
    pcap_t * handle; // handler of the interface by pcap 

    struct bpf_program bpf; 
    bpf_u_int32 mask; // network mask 
    bpf_u_int32 ip; // network ip 
    struct in_addr addr; // network number 

    int ret; 

    /* get mask & ip */ 
    if(pcap_lookupnet(interface, &ip, &mask, err) == -1) { 
     fprintf(stderr, "Couldn't get netmask for device %s: %s\n",interface,err); 
     exit(EXIT_FAILURE); 
    } 

    handle = pcap_create(interface,err); 
    if (handle == NULL) { 
     fprintf(stderr,"Error pcap_create() : %s \n",err); 
     exit(EXIT_FAILURE); 
    } 
    if(set_options(handle) != 0) { 
     fprintf(stderr,"Exiting\n"); 
     exit(EXIT_FAILURE); 
    } 
    if (activate(handle) != 0) { 
     fprintf(stderr,"Exiting\n"); 
     exit(EXIT_FAILURE); 
    } 

    /* FILTER PART */ 
    if(filter != NULL) { 
     if(pcap_compile(handle,&bpf,filter,0,ip) == -1){ 
      fprintf(stderr,"Couldn't compile filter expr %s : %s\n",filter,pcap_geterr(handle)); 
      exit(EXIT_FAILURE); 
     } 
     if(pcap_setfilter(handle, &bpf) == -1) { 
      fprintf(stderr,"Couldn't install filter %s : %s\n",filter,pcap_geterr(handle)); 
      exit(EXIT_FAILURE); 
     } 
    } 

    /* SNIFF starts */ 
    printf("Sniffing starting on %s ...\n",interface); 
    pcap_loop(handle,packet_count,sniff_callback,NULL); 

    pcap_freecode(&bpf); 
    pcap_close(handle); 

    return EXIT_SUCCESS; 
} 
void usage() { 
    printf("sniff interface [filter] [count]"); 
    printf("interface is the interface you want to listen on. It will try to put it in monitor mode"); 
    printf("filter can be a filter for libpcap to apply for packets it reads"); 
} 
int main(int argc, char * argv[]) 
{ 


    int i = 0; // counter 
    int ret; 
    char * default_filter = "ip"; 
    char * filter; 

    int pcount = -1; //take all packet by defaults 

    char * interface; 
    if(argc < 2) { 
     fprintf(stderr, "No interfaces specified in arguments\n"); 
     usage(); 
     exit(EXIT_FAILURE); 
    } 
    // take command line filter 
    if(argc > 2) { 
     filter = argv[2]; 
    } else { 
     filter = default_filter; 
    } 
    // take command line packet count limit 
    if(argc > 3) { 
     pcount = atoi(argv[3]); 
    } 

    fprintf(stdout,"Args : "); 
    for(i = 0; i < argc; i++) { 
     fprintf(stdout,"\t%s",argv[i]); 
    } 
    printf("\n"); 

    interface = argv[1]; 

    sniffing_method(interface,filter,pcount); 



} 

А вот один выход (все попытки дает тот же результат, так или иначе)

Received packet number 2 ==> 42 
Ethernet Layer 
    Source: 00:ee:bd:aa:f4:98: 
    Dest: FF:FF:FF:FF:FF:FF: 
    Type: ARP 
ARP Layer 
    Hardware type: 00 
    Protocol type: 00 
    Hardware addresses length: 0 
    Protocol addresses length: 0 
    Operation code: 0 
    Hardware sender: 20e9a152:20e9a152:20e9a152:20e9a152:20e9a152:20e9a152: 
    Software sender: 20e9a158:20e9a158:20e9a158:20e9a158: 
Error : ARP packet does not contain a Hardware type Ethernet -> 0 
------------------------- 
------------------------- 
Received packet number 3 ==> 42 
Ethernet Layer 
    Source: 00:ee:bd:aa:f4:98: 
    Dest: FF:FF:FF:FF:FF:FF: 
    Type: ARP 
ARP Layer 
    Hardware type: 00 
    Protocol type: 00 
    Hardware addresses length: 0 
    Protocol addresses length: 0 
    Operation code: 0 
    Hardware sender: 20e5a152:20e5a152:20e5a152:20e5a152:20e5a152:20e5a152: 
    Software sender: 20e5a158:20e5a158:20e5a158:20e5a158: 

ответ

1

Эта часть является неправильным:

void handleARP(const struct pkt_eth * eth) { 

    const struct pkt_arp * arp = (const struct pkt_arp *) (eth + ETH_SIZE); 

Здесь вы передаете в struct pkt_eth*, к которому вы добавляете ETH_SIZE. Арифметика указателя переходит к следующему элементу, а не к следующему байту. Вы, по существу, глядя sizeof(struct pkt_eth) * ETH_SIZE байт мимо указателя передается в.

Вы должны просто сделать

const struct pkt_arp * arp = (const struct pkt_arp *) (eth + 1); 

(или передать в неподписанные символ *, который уже начинается на слое, который вы хотите декодировать.)

+0

Я полностью отредактировал свой код, и он работает, но спасибо за (правильный) ответ в любом случае;) – Nikkolasg

 Смежные вопросы

  • Нет связанных вопросов^_^