Description: [PATCH 2/3] arpspoof: allow use of multiple targets. Last hunk modified by João Salavisa in order to fix a bug with "-t" option of arpspoof. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=706766 fo more information. Author: Stefan Tomanek --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ --- a/arpspoof.8 +++ b/arpspoof.8 @@ -25,7 +25,7 @@ Specify the interface to use. .IP "\fB-t \fItarget\fR" Specify a particular host to ARP poison (if not specified, all hosts -on the LAN). +on the LAN). Repeat to specify multiple hosts. .IP "\fB\-r\fR" Poison both hosts (host and target) to capture traffic in both directions. (only valid in conjuntion with \-t) --- a/arpspoof.c +++ b/arpspoof.c @@ -29,9 +29,14 @@ extern char *ether_ntoa(struct ether_addr *); +struct host { + in_addr_t ip; + struct ether_addr mac; +}; + static libnet_t *l; -static struct ether_addr spoof_mac, target_mac; -static in_addr_t spoof_ip, target_ip; +static struct host spoof = {0}; +static struct host *targets; static char *intf; static int poison_reverse; @@ -133,30 +138,46 @@ return (0); } +static int arp_find_all() { + struct host *target = targets; + while(target->ip) { + if (arp_find(target->ip, &target->mac)) { + return 1; + } + target++; + } + + return 0; +} + static void cleanup(int sig) { - int fw = arp_find(spoof_ip, &spoof_mac); - int bw = poison_reverse && target_ip && arp_find(target_ip, &target_mac); + int fw = arp_find(spoof.ip, &spoof.mac); + int bw = poison_reverse && targets[0].ip && arp_find_all(); int i; fprintf(stderr, "Cleaning up and re-arping targets...\n"); for (i = 0; i < 5; i++) { - /* XXX - on BSD, requires ETHERSPOOF kernel. */ - if (fw) { - arp_send(l, ARPOP_REPLY, - (u_int8_t *)&spoof_mac, spoof_ip, - (target_ip ? (u_int8_t *)&target_mac : NULL), - target_ip); - /* we have to wait a moment before sending the next packet */ - sleep(1); - } - if (bw) { - arp_send(l, ARPOP_REPLY, - (u_int8_t *)&target_mac, target_ip, - (u_int8_t *)&spoof_mac, - spoof_ip); - sleep(1); + struct host *target = targets; + while(target->ip) { + /* XXX - on BSD, requires ETHERSPOOF kernel. */ + if (fw) { + arp_send(l, ARPOP_REPLY, + (u_int8_t *)&spoof.mac, spoof.ip, + (target->ip ? (u_int8_t *)&target->mac : NULL), + target->ip); + /* we have to wait a moment before sending the next packet */ + sleep(1); + } + if (bw) { + arp_send(l, ARPOP_REPLY, + (u_int8_t *)&target->mac, target->ip, + (u_int8_t *)&spoof.mac, + spoof.ip); + sleep(1); + } + target++; } } @@ -171,10 +192,15 @@ char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c; + int n_targets; + spoof.ip = 0; intf = NULL; - spoof_ip = target_ip = 0; poison_reverse = 0; + n_targets = 0; + + /* allocate enough memory for target list */ + targets = calloc( argc+1, sizeof(struct host) ); while ((c = getopt(argc, argv, "ri:t:h?V")) != -1) { switch (c) { @@ -182,7 +208,7 @@ intf = optarg; break; case 't': - if ((target_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) + if ((targets[n_targets++].ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) usage(); break; case 'r': @@ -198,12 +224,12 @@ if (argc != 1) usage(); - if (poison_reverse && !target_ip) { + if (poison_reverse && !n_targets) { errx(1, "Spoofing the reverse path (-r) is only available when specifying a target (-t)."); usage(); } - if ((spoof_ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) + if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) usage(); if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) @@ -211,15 +237,19 @@ if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) errx(1, "%s", libnet_ebuf); - - if (target_ip != 0 && !arp_find(target_ip, &target_mac)) - errx(1, "couldn't arp for host %s", - libnet_addr2name4(target_ip, LIBNET_DONT_RESOLVE)); + + struct host *target = targets; + while(target->ip) { + if (target->ip != 0 && !arp_find(target->ip, &target->mac)) + errx(1, "couldn't arp for host %s", + libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); + target++; + } if (poison_reverse) { - if (!arp_find(spoof_ip, &spoof_mac)) { + if (!arp_find(spoof.ip, &spoof.mac)) { errx(1, "couldn't arp for spoof host %s", - libnet_addr2name4(spoof_ip, LIBNET_DONT_RESOLVE)); + libnet_addr2name4(spoof.ip, LIBNET_DONT_RESOLVE)); } } @@ -228,12 +258,20 @@ signal(SIGTERM, cleanup); for (;;) { - arp_send(l, ARPOP_REPLY, NULL, spoof_ip, - (target_ip ? (u_int8_t *)&target_mac : NULL), - target_ip); - if (poison_reverse) { - arp_send(l, ARPOP_REPLY, NULL, target_ip, (uint8_t *)&spoof_mac, spoof_ip); + if (!n_targets) { + arp_send(l, ARPOP_REPLY, my_ha, spoof.ip, brd_ha, 0, my_ha); + } else { + struct host *target = targets; + while(target->ip) { + arp_send(l, ARPOP_REPLY, NULL, spoof.ip, + (target->ip ? (u_int8_t *)&target->mac : NULL), + target->ip); + if (poison_reverse) { + arp_send(l, ARPOP_REPLY, NULL, target->ip, (uint8_t *)&spoof.mac, spoof.ip); + } + target++; } + } sleep(2); }