1
votes

I'm currently making a little program to send an arp request, the program seems to work because wireshark captures the packets, but there is something strange; first of all the destination host does not receive the packets (I get no response and even running wireshark on the target doesn't display anything), and secondly the packet seem to contain different information than those the program inserted in the packet itself. I explain myself better: the packet should have the ethernet header with destination mac address, source mac address and protocol type, and then the arp header. The arp header is not recognized by wireshark which also shows something different instead of the ethernet header and I don't undertand why. Can someone help me please?

#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++;
    }
}

Here is the wireshark screenshot

enter image description here

1
Please try to add images in the post not on links as they expire and it is not useful for future readersSir. Hedgehog
@Sir. Hedgehog, He can't though,because he hsa got below 10 reputation.RUL
@RUL well thats true and unfortunate. i guess thats a meta issueSir. Hedgehog

1 Answers

1
votes

Comparing "data" part of the packet on the wire with example of ARP packet you can verify, that all necessary bytes are actually in place. The problem happens in Ethernet header of the frame, where protocol identifier is 0x0000 instead of 0x0806. This is why Wireshark doesn't even try to decode packet as ARP, but dispalys it as raw data instead.

It looks like you missed part of initialization of ll1. Adding this line seems to fix the issue:

ll1.sll_protocol = htons(ETH_P_ARP);