未收到ARP请求,wireshark无法读取arp标头

时间:2018-11-02 13:54:44

标签: c wireshark arp

我当前正在编写一个小程序来发送arp请求,该程序似乎可以工作,因为Wireshark捕获了数据包,但是有些奇怪;首先,目标主机未接收到数据包(我没有响应,甚至在目标计算机上运行wireshark也不显示任何内容),其次,数据包似乎包含的信息与插入数据包本身的程序不同。我对自己进行了更好的解释:数据包应具有带有目标mac地址,源mac地址和协议类型的以太网标头,然后是arp标头。 Wireshark无法识别arp标头,它也显示了与以太网标头不同的东西,我也不知道为什么。有人可以帮我吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <ifaddrs.h>

#define TRUE 1

/* in the arp header structure defined in the linux header files access to certain fields is prohibited 
 * so we define our own ARP packet with all the fields needed to send an ARP spoofed packet */
struct arp_packet{
    unsigned char h_dest[ETH_ALEN];     /* destination ETH address (MAC address) */     
    unsigned char h_source[ETH_ALEN];   /* source ETH address (MAC address) */
    unsigned short h_proto;         /* packet protocol: ETH_P_ARP */
    unsigned short ar_hrd;          /* format of hardware address: ARPHDR_ETHER */
    unsigned short ar_proto;        /* format of protocol address: ETH_P_IP */
    unsigned char ar_hlen;          /* length of hardware address: 6 */
    unsigned char ar_plen;          /* length of protocol address: 4 */
    unsigned short ar_op;           /* type of ARP packet: ARPOP_REQUEST */
    unsigned char ar_senderHaddr[ETH_ALEN]; /* sender MAC address */
    unsigned char ar_senderIP[4];       /* sender IP address */
    unsigned char ar_targetHaddr[ETH_ALEN]; /* target MAC address */
    unsigned char ar_targetIP[4];       /* target IP address */
};

void mac_parser(char *mac_address, unsigned char *dest);

int main(int argc, char **argv){
    /* for the following structure we need to fill the following fields 
     * sll_family: PF_PACKET
     * sll_addr: MAC address of receiver
     * sll_halen: ETHER_ADDR_LEN
     * sll_ifindex: interface index number */
    struct sockaddr_ll ll1 = {0}, ll2 = {0};
    /* socket descriptor */
    int fd;
    /* structure for ioctl */
    struct ifreq ifr = {0};
    /* structure for getifaddrs */
    struct ifaddrs *ifaddr, *ifa;
    /* arp packets */
    struct arp_packet A;
    /* ip addresses */
    struct in_addr A_ip, B_ip;
    struct hostent *host;

    if(argc < 3){
        fprintf(stderr, "Usage: %s <IP address of host A> <MAC of host A> <IP address of host B> <MAC address of host B>\n", argv[0]);
        exit(1);
    }
    /* access the data link layer with PF_PACKET */
    if((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(2);
    }
    /* get a valid interface to use */
    if(getifaddrs(&ifaddr) == -1){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(3);
    }
    for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next){
        if(ifa->ifa_flags & IFF_UP){
            if(ifa->ifa_flags & IFF_RUNNING){
                if(strcmp(ifa->ifa_name, "lo")){
                    strcpy(ifr.ifr_name, ifa->ifa_name);
                    break;
                }
            }
        }
    }
    /* get the interface index number */
    if(ioctl(fd, SIOCGIFINDEX, &ifr) == -1){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(4);
    }
    /* Put ip addresses in the network format */
    if((host = gethostbyname(argv[1])) == NULL){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(5);
    }
    A_ip = *(struct in_addr *)host->h_addr;
    printf("%s - %s\n", argv[1], inet_ntoa(A_ip));
    if((host = gethostbyname(argv[3])) == NULL){
        fprintf(stderr, "%s\n", strerror(errno));
        exit(6);
    }
    B_ip = *(struct in_addr *)host->h_addr;
    /* fill lls structures */
    ll1.sll_family = PF_PACKET;
    ll1.sll_halen = ETHER_ADDR_LEN;
    ll1.sll_ifindex = ifr.ifr_ifindex;
    mac_parser(argv[2], ll1.sll_addr);
    /* fill arp_packets */
    memcpy(A.h_dest, ll1.sll_addr, ETH_ALEN);
    mac_parser(argv[4], ll2.sll_addr);
    memcpy(A.h_source, ll2.sll_addr, ETH_ALEN);
    A.h_proto = htons(ETH_P_ARP);
    A.ar_hrd = htons(ARPHRD_ETHER);
    A.ar_proto = htons(ETH_P_IP);
    A.ar_hlen = 6;
    A.ar_plen = 4;
    A.ar_op = htons(ARPOP_REQUEST);
    memcpy(A.ar_senderHaddr, A.h_source, ETH_ALEN);
    memcpy(A.ar_targetHaddr, A.h_dest, ETH_ALEN);
    memcpy(A.ar_senderIP, &B_ip, 4);
    memcpy(A.ar_targetIP, &A_ip, 4);
    A.pool = 0;
    /* send packets in a loop */
    while(TRUE){
        if(sendto(fd, &A, sizeof(A), 0, (struct sockaddr *)&ll1, sizeof(ll1)) == -1){
            fprintf(stderr, "%s\n", strerror(errno));
            exit(6);
        }
        sleep(1);
    }
    return 0;
}

void mac_parser(char *mac_address, unsigned char *dest){

    unsigned transition;
    int i = 0;
    char *token = strtok(mac_address, ":");

    while(token){
        sscanf(token, "%x", &transition);
        dest[i] = (unsigned char)transition;
        token = strtok(NULL, ":");
        i++;
    }
}

这是Wireshark屏幕截图

enter image description here

1 个答案:

答案 0 :(得分:0)

将线路上数据包的“数据”部分与ARP数据包示例进行比较,可以确定所有必要的字节实际上都已就位。问题发生在帧的以太网报头中,其中协议标识符为0x0000而不是0x0806。这就是Wireshark甚至不尝试将数据包解码为ARP而是将其显示为原始数据的原因。

您似乎错过了ll1初始化的一部分。添加此行似乎可以解决此问题:

ll1.sll_protocol = htons(ETH_P_ARP);