/*
 * Sniffoze v0.5 for winNT/2k by crazyl0rd
 * (lame sniffer but i wanted to test the winPcap)
 * compiled with only 0 error/warning with MS VC 5 & djgpp
 *
 * winPcap --> http://netgroup-serv.polito.it/winpcap/
 * download the developper pack
 */

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <packet32.h>
#include <time.h>

#define MAX_ETHERNET_FRAME_SIZE 1514
#define ERREUR -1
#define MAX_CR 5

char buffer[256000];
char carte_rezo_liste[MAX_CR][1024];
int  mode_log=0, mode_quiet=0;
FILE *logfile;


// ---------------------------------------------------------------
void Usage() {
	printf("\nSniffoze v0.5 for winNT/2k by crazyl0rd\n");
	printf("you will need winPcap in order to compil & use it\n\n");
	printf("\t-q           : quiet mode\n");
	printf("\t-l <logfile> : logging mode\n");
	printf("\t-h           : this help\n");
	exit(ERREUR);
}
// ---------------------------------------------------------------
void AffichePacket(LPPACKET packet) {

	u_int  i, j, nb_lignes, ulen, nbytes, capture_len, real_len, off=0;
	char   *current_char, *pLine, *base, *buf;
	char tmp[96], tmp2[96]; // bof and i don't care
	struct bpf_hdr *hdr;

	nbytes = packet->ulBytesReceived;
	buf = packet->Buffer;
	off = 0;

	while(off<nbytes){	

		if(kbhit())
			return;

		hdr   = (struct bpf_hdr *)(buf+off);

		real_len     = hdr->bh_datalen;
		capture_len  = hdr->bh_caplen;
		off   += hdr->bh_hdrlen;

		sprintf(tmp, "Lenght: %i (0x%x)\n", real_len, real_len);
		if (!mode_quiet) printf("%s", tmp);
		if (mode_log) fprintf(logfile, "%s", tmp);

		nb_lignes = (capture_len+15)/16;

		current_char = (char*) (buf+off);
		base=current_char;
		off=Packet_WORDALIGN(off+real_len);

		for (i=0; i<nb_lignes; ++i) {

			pLine = current_char;
			sprintf(tmp2, "0x%.2x  ", current_char-base);
			// "0x00?  "
			strcpy(tmp, tmp2);

			ulen = capture_len;
			ulen = ( ulen > 16 ) ? 16 : ulen;
			capture_len -= ulen;

			for ( j=0; j<ulen; j++ ) {
				// ?? (hex)
				sprintf(tmp2, "%02x ", *(BYTE *)current_char++ );
				// "0x00?  ?? ?? ?? ??"
				strcat(tmp, tmp2);
			}

			// "0x00?  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??   "
			strcat(tmp, "   ");
			strcpy(tmp2, "");

			if (ulen < 16)
				sprintf(tmp2, "%*s", (16-ulen)*3, " " );

			strcat(tmp, tmp2);
			current_char = pLine;

			for ( j=0; j<ulen; j++, current_char++ ) {
				// ? (ascii)
				sprintf(tmp2, "%c", isprint( *current_char ) ? *current_char : '.');
				// "0x00?  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??   ????"
				strcat(tmp, tmp2);
			}

			// "0x00?  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??   ????????????????\n"
			strcat(tmp, "\n");

			if (!mode_quiet) printf("%s", tmp);
			if (mode_log) fprintf(logfile, "%s", tmp);
		}
		printf("\n");
		if (mode_log) fprintf(logfile, "\n");
	}
} 

// ---------------------------------------------------------------
void CapturePackets(char *carte) {

	LPADAPTER carte_rezo;
	LPPACKET   packet;
	struct bpf_stat stat;

	carte_rezo = PacketOpenAdapter(carte);

	if (!carte_rezo || (carte_rezo->hFile == INVALID_HANDLE_VALUE)) {
		printf("unable to sniff from this adapter"); 
		exit(ERREUR);
	}

	PacketSetHwFilter(carte_rezo, NDIS_PACKET_TYPE_PROMISCUOUS);
	PacketSetBuff(carte_rezo, 512000);
	PacketSetReadTimeout(carte_rezo, 1500);
	
	if((packet = PacketAllocatePacket()) == NULL) {
		printf("\nError: unable to allocate packet structure.");
		exit(ERREUR);
	}

	PacketInitPacket(packet, (char*) buffer, 256000);

	while(!kbhit()) {

		if(PacketReceivePacket(carte_rezo, packet, TRUE) == FALSE){
			printf("Error: unable to receive packets");
			exit(ERREUR);
		}
		AffichePacket(packet);
	}

	PacketGetStats(carte_rezo, &stat);

	printf("===================================================================\n");
	printf("packets received: %d.\n", stat.bs_recv);

	if (stat.bs_drop)
		printf("packets lost: %d\n", stat.bs_drop);

	PacketFreePacket(packet);
	PacketCloseAdapter(carte_rezo);
}

// ---------------------------------------------------------------
int main(int argc, char **argv) {

	int    i=0, cpt, n, choix;
	WCHAR  *temp, *temp1, carte_rezo_nom[512];
	u_long carte_rezo_size=512;
	char   *log;
	//char   log[20];
	
	if (((argc % 2) == 0))
		Usage();

	// fucking getopt() de barbare au napolitain (trip perso, faut pas chercher à comprendre)

	for (cpt=1; cpt<argc; cpt+=2) {
		switch (argv[cpt][1]) {

			case 'q':
				mode_quiet=1;
				break;
			case 'l':
				mode_log=1;
				log = malloc(sizeof(argv[cpt+1]));
				strcpy(log, argv[cpt+1]);
				break;
			case 'h':
				Usage();
				break;
			default:
				break;
		}
	}

	if (mode_quiet && !mode_log) {
		printf("no log and no display, are you sure you know what you want\n");
		exit(ERREUR);
	}

	PacketGetAdapterNames(carte_rezo_nom, &carte_rezo_size);
	temp = carte_rezo_nom;
	temp1 = carte_rezo_nom;
	printf("\n");
	while ((*temp != '\0') || (*(temp-1) != '\0')) {
		if (*temp == '\0') {
			memcpy(carte_rezo_liste[i],temp1,(temp-temp1)*2);
			temp1=temp+1;
			i++;
		}
		temp++;
	}

	n=i;

	for (i=0;i<n;i++) {
		wprintf(L"\t%d - %s\n",i,carte_rezo_liste[i]);
	}
	printf("\n");
		
	printf("Choose an adapter >>> ");
	scanf("%d",&choix);

	if (choix>n || choix<0) {
		printf("\ninvalid adapter"); 
		return (ERREUR);
	}
	
	if (mode_log) {
		if( (logfile = fopen(log, "w+")) == NULL) {
			printf("Cannot open file %s", log);
			exit(ERREUR);
		}
	}

	CapturePackets(carte_rezo_liste[choix]);

	return (0);
}
