219 lines
6.5 KiB
Diff
219 lines
6.5 KiB
Diff
|
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++;
|
||
|
}
|