You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
6.5 KiB
218 lines
6.5 KiB
Patch by Stefan Tomanek <stefan@pico.ruhr.de> for dsniff >= 2.4b1 to allow the |
|
selection of source hw address. |
|
|
|
In certain networks, sending with the wrong hardware source address can jeopardize |
|
the network connection of the host running arpspoof. This patch makes it possible |
|
to specify whether arpspoof should use the own hardware address or the one of the |
|
real host when resetting the arp table of the target systems; it is also possible |
|
to use both. |
|
|
|
For some more information, please have a look to Debian bug ID #650752. |
|
|
|
--- dsniff-2.4/arpspoof.8 2013-12-20 20:54:25.000000000 +0100 |
|
+++ dsniff-2.4/arpspoof.8.arpspoof_hwaddr 2013-12-20 20:55:19.000000000 +0100 |
|
@@ -9,7 +9,7 @@ |
|
.na |
|
.nf |
|
.fi |
|
-\fBarpspoof\fR [\fB\-i \fIinterface\fR] [\fB\-t \fItarget\fR] [\fB\-r\fR] \fIhost\fR |
|
+\fBarpspoof\fR [\fB\-i \fIinterface\fR] [\fB\-c \fIown|host|both\fR] [\fB\-t \fItarget\fR] [\fB\-r\fR] \fIhost\fR |
|
.SH DESCRIPTION |
|
.ad |
|
.fi |
|
@@ -23,6 +23,13 @@ |
|
.SH OPTIONS |
|
.IP "\fB-i \fIinterface\fR" |
|
Specify the interface to use. |
|
+.IP "\fB-c \fIown|host|both\fR" |
|
+Specify which hardware address t use when restoring the arp configuration; |
|
+while cleaning up, packets can be send with the own address as well as with |
|
+the address of the host. Sending packets with a fake hw address can disrupt |
|
+connectivity with certain switch/ap/bridge configurations, however it works |
|
+more reliably than using the own address, which is the default way arpspoof |
|
+cleans up afterwards. |
|
.IP "\fB-t \fItarget\fR" |
|
Specify a particular host to ARP poison (if not specified, all hosts |
|
on the LAN). Repeat to specify multiple hosts. |
|
--- dsniff-2.4/arpspoof.c 2013-12-20 20:54:25.000000000 +0100 |
|
+++ dsniff-2.4/arpspoof.c.arpspoof_hwaddr 2013-12-20 21:02:10.000000000 +0100 |
|
@@ -40,37 +40,36 @@ |
|
static char *intf; |
|
static int poison_reverse; |
|
|
|
+static uint8_t *my_ha = NULL; |
|
+static uint8_t *brd_ha = "\xff\xff\xff\xff\xff\xff"; |
|
+ |
|
+static int cleanup_src_own = 1; |
|
+static int cleanup_src_host = 0; |
|
+ |
|
static void |
|
usage(void) |
|
{ |
|
fprintf(stderr, "Version: " VERSION "\n" |
|
- "Usage: arpspoof [-i interface] [-t target] [-r] host\n"); |
|
+ "Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host\n"); |
|
exit(1); |
|
} |
|
|
|
static int |
|
-arp_send(libnet_t *l, int op, u_int8_t *sha, |
|
- in_addr_t spa, u_int8_t *tha, in_addr_t tpa) |
|
+arp_send(libnet_t *l, int op, |
|
+ u_int8_t *sha, in_addr_t spa, |
|
+ u_int8_t *tha, in_addr_t tpa, |
|
+ u_int8_t *me) |
|
{ |
|
int retval; |
|
|
|
- if (sha == NULL && |
|
- (sha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) { |
|
- return (-1); |
|
- } |
|
- if (spa == 0) { |
|
- if ((spa = libnet_get_ipaddr4(l)) == -1) |
|
- return (-1); |
|
- } |
|
- if (tha == NULL) |
|
- tha = "\xff\xff\xff\xff\xff\xff"; |
|
+ if (!me) me = sha; |
|
|
|
libnet_autobuild_arp(op, sha, (u_int8_t *)&spa, |
|
tha, (u_int8_t *)&tpa, l); |
|
- libnet_build_ethernet(tha, sha, ETHERTYPE_ARP, NULL, 0, l, 0); |
|
+ libnet_build_ethernet(tha, me, ETHERTYPE_ARP, NULL, 0, l, 0); |
|
|
|
fprintf(stderr, "%s ", |
|
- ether_ntoa((struct ether_addr *)sha)); |
|
+ ether_ntoa((struct ether_addr *)me)); |
|
|
|
if (op == ARPOP_REQUEST) { |
|
fprintf(stderr, "%s 0806 42: arp who-has %s tell %s\n", |
|
@@ -129,7 +128,7 @@ |
|
/* XXX - force the kernel to arp. feh. */ |
|
arp_force(ip); |
|
#else |
|
- arp_send(l, ARPOP_REQUEST, NULL, 0, NULL, ip); |
|
+ arp_send(l, ARPOP_REQUEST, NULL, 0, NULL, ip, NULL); |
|
#endif |
|
sleep(1); |
|
} |
|
@@ -156,17 +155,22 @@ |
|
int fw = arp_find(spoof.ip, &spoof.mac); |
|
int bw = poison_reverse && targets[0].ip && arp_find_all(); |
|
int i; |
|
+ int rounds = (cleanup_src_own*5 + cleanup_src_host*5); |
|
|
|
fprintf(stderr, "Cleaning up and re-arping targets...\n"); |
|
- for (i = 0; i < 5; i++) { |
|
+ for (i = 0; i < rounds; i++) { |
|
struct host *target = targets; |
|
while(target->ip) { |
|
+ uint8_t *src_ha = NULL; |
|
+ if (cleanup_src_own && (i%2 || !cleanup_src_host)) { |
|
+ src_ha = my_ha; |
|
+ } |
|
/* 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); |
|
+ (target->ip ? (u_int8_t *)&target->mac : brd_ha), |
|
+ target->ip, src_ha); |
|
/* we have to wait a moment before sending the next packet */ |
|
sleep(1); |
|
} |
|
@@ -174,7 +178,7 @@ |
|
arp_send(l, ARPOP_REPLY, |
|
(u_int8_t *)&target->mac, target->ip, |
|
(u_int8_t *)&spoof.mac, |
|
- spoof.ip); |
|
+ spoof.ip, src_ha); |
|
sleep(1); |
|
} |
|
target++; |
|
@@ -193,6 +197,7 @@ |
|
char libnet_ebuf[LIBNET_ERRBUF_SIZE]; |
|
int c; |
|
int n_targets; |
|
+ char *cleanup_src = NULL; |
|
|
|
spoof.ip = 0; |
|
intf = NULL; |
|
@@ -202,7 +207,7 @@ |
|
/* allocate enough memory for target list */ |
|
targets = calloc( argc+1, sizeof(struct host) ); |
|
|
|
- while ((c = getopt(argc, argv, "ri:t:h?V")) != -1) { |
|
+ while ((c = getopt(argc, argv, "ri:t:c:h?V")) != -1) { |
|
switch (c) { |
|
case 'i': |
|
intf = optarg; |
|
@@ -214,6 +219,9 @@ |
|
case 'r': |
|
poison_reverse = 1; |
|
break; |
|
+ case 'c': |
|
+ cleanup_src = optarg; |
|
+ break; |
|
default: |
|
usage(); |
|
} |
|
@@ -229,6 +237,29 @@ |
|
usage(); |
|
} |
|
|
|
+ if (!cleanup_src || strcmp(cleanup_src, "own") == 0) { /* default! */ |
|
+ /* only use our own hw address when cleaning up, |
|
+ * not jeopardizing any bridges on the way to our |
|
+ * target |
|
+ */ |
|
+ cleanup_src_own = 1; |
|
+ cleanup_src_host = 0; |
|
+ } else if (strcmp(cleanup_src, "host") == 0) { |
|
+ /* only use the target hw address when cleaning up; |
|
+ * this can screw up some bridges and scramble access |
|
+ * for our own host, however it resets the arp table |
|
+ * more reliably |
|
+ */ |
|
+ cleanup_src_own = 0; |
|
+ cleanup_src_host = 1; |
|
+ } else if (strcmp(cleanup_src, "both") == 0) { |
|
+ cleanup_src_own = 1; |
|
+ cleanup_src_host = 1; |
|
+ } else { |
|
+ errx(1, "Invalid parameter to -c: use 'own' (default), 'host' or 'both'."); |
|
+ usage(); |
|
+ } |
|
+ |
|
if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) |
|
usage(); |
|
|
|
@@ -253,6 +284,10 @@ |
|
} |
|
} |
|
|
|
+ if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) { |
|
+ errx(1, "Unable to determine own mac address"); |
|
+ } |
|
+ |
|
signal(SIGHUP, cleanup); |
|
signal(SIGINT, cleanup); |
|
signal(SIGTERM, cleanup); |
|
@@ -260,11 +295,11 @@ |
|
for (;;) { |
|
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); |
|
+ arp_send(l, ARPOP_REPLY, my_ha, spoof.ip, |
|
+ (target->ip ? (u_int8_t *)&target->mac : brd_ha), |
|
+ target->ip, my_ha); |
|
if (poison_reverse) { |
|
- arp_send(l, ARPOP_REPLY, NULL, target->ip, (uint8_t *)&spoof.mac, spoof.ip); |
|
+ arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&spoof.mac, spoof.ip, my_ha); |
|
} |
|
target++; |
|
}
|
|
|