Basic Sniffer Tutorial



Похожие документы
Socket. Nei sistemi operativi moderni i servizi disponibili in rete si basano principalmente sul modello client/server.

I Socket. Laboratorio Software M. Grotto R. Farina

Socket. Nei sistemi operativi moderni i servizi disponibili in rete si basano principalmente sul modello client/server.

Cenni di programmazione distribuita in C++ Mauro Piccolo

unsigned long inet_addr(cp) char *cp;

Interazione (TCP) Client-Server con le socket

Introduzione allo sniffing

Una semplice applicazione client/server 1

COMUNICAZIONE TRA PROCESSI REMOTI IN UNIX

L uso di Socket UDP. TCP vs. UDP UDP

Uso di sniffer ed intercettazione del traffico IP

Socket TCP. prima parte

IPC Inter Process Communication

Esempio 1: stampa locale di file remoto

Reti (già Reti di Calcolatori )

IP - SPOOFING by styx^

I/O su Socket TCP: read()

Interazione (TCP) Client-Server con le socket

CREARE UNA LIBRERIA IN C

Esercitazione [6] Client/Server con Socket

Creare una applicazione Winsock di base

Una prima applicazione in C per l utilizzo delle socket

L interfaccia socket

rsystem Maximiliano Marchesi

Socket TCP. seconda parte

Introduzione alla programmazione in C

Opzioni del Socket. Socket Options. Opzioni di Livello Socket. Livello delle Opzioni

DATAGRAM SOCKET. Angelastro Sergio Diomede Antonio Viterbo Tommaso

Corso di Laurea in Ingegneria Informatica. Corso di Reti di Calcolatori I

Funzioni in C. Violetta Lonati

L uso di Socket UDP. Usiamo le API Winsock incluse in <Winsock.h> A.A. 2005/06. Dott.ssa Valeria Carofiglio

Raw socket. L intercettazione di un pacchetto IP

Laboratorio di Programmazione 1. Docente: dr. Damiano Macedonio Lezione 18 31/03/2014

Le funzioni in C. I programmi C sono costituiti da definizioni di variabili e funzioni.

request reply richiesta client processo di servizio processo server principale From - Valeria Cardellini, Corso Sist. Distr. A.A.

Protocolli di Comunicazione

Creare un'elementare backdoor in C in ambiente UNIX

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 6

Gestione dei File in C

ESERCIZIO NUMERO 1 ESERCIZIO NUM. 2

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

TECNOLOGIE E PROGETTAZIONE DI SISTEMI INFORMATICI E DI TELECOMUNICAZIONI

Esercitazione di Lab. di Sistemi Operativi 1 a.a. 2011/ Comunicazione Tra Processi (IPC) Parte -


Introduzione allo sniffing

Il livello Network del TCP/IP. Il protocollo IP (versione 4)

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

Controllo Winsock di Visual Basic

Innanzitutto, esistono diversi modi per realizzare una rete o più reti messe insieme; vi illustro la mia soluzione :

Introduzione allo sniffing

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

Reti di Telecomunicazioni Mobile IP Mobile IP Internet Internet Protocol header IPv4 router host indirizzi IP, DNS URL indirizzo di rete

Basi di network programming sotto Unix/Linux (draft version) Claudio Piciarelli

CORSO DI RETI SSIS. Lezione n.2. 2 Novembre 2005 Laura Ricci

Il livello di Trasporto del TCP/IP

IP (Internet Protocol) sta al livello 2 della scala Tcp/Ip o al livello 3 della scala ISO/OSI. Un indirizzo IP identifica in modo logico (non fisico

Reti. Reti. IPv4: concetti fondamentali. arp (address resolution protocol) Architettura a livelli (modello OSI)

Laboratorio di Programmazione in Rete

TCP/IP: summary. Lorenzo Cavallaro, Andrea Lanzi

Socket API per il Multicast

INTERNET DOMAIN SOCKETS (Cap.59)

Guida all utilizzo del compilatore lcc-win32 per creare una applicazione console

Esercitazione [5] Input/Output su Socket

Lab. di Sistemi Operativi - Esercitazione n 7- -Gestione dei processi Unix-

Sicurezza nelle reti

Транскрипт:

Basic Sniffer Tutorial LnZ <lnz@spine-group.org >Aspinall <aspi@spine-group.org > S.P.I.N.E. Research Group April 2, 2003 Abstract Con questo semplice esempio cerchero di mostrarvi l uso di base delle socket raw e delle ioctl necessarie a scrivere uno sniffer nel modo piu semplice possibile. E necessaria una conoscenza di base dei protocolli di rete prima di cominciare a scrivere anche solo una linea di codice di uno sniffer, se non ne avete vi consiglio di darvi un occhiata ai vari Stevens (se non sapete cosa siano vergognatevi ;) ). Il nostro amico Google vi dar una mano, provate con una semplice ricerca di TCP/IP Illustrated 1. Il codice non e assolutamente ottimizzato, e studiato per essere letto facilmente. Contents 1 Descrizione Codice 1 2 Codice Sniffer in C 6 3 Esempio di utilizzo Raw Sockets <Aspinall > 7 4 Ringraziamenti 11 1 Descrizione Codice Iniziamo subito con la definizione delle strutture che il nostro sniffer utilizzera qui di seguito vi riporto le strutture per una macchina Little Endian : typedef struct { unsigned int h_len:4; //Lunghezza Header ip unsigned int ip_version:4; //Versione protocollo IP //Se avete una macchina "Big Endian" invertite i due campi precedenti unsigned char tos; //Tipo del servizio unsigned short t_len; //Lunghezza totale unsigned short ident; //IP Ident unsigned short frag_and_flags; //Frammenti e Flags unsigned char ttl; //Time To Live unsigned char proto; //Protocollo di Trasporto unsigned short checksum; //Checksum pacchetto IP 1 Guardate la bibliografia per i riferimneti 1

unsigned int source_ip;//ip sorgente unsigned int dest_ip;//ip destinazione IP_Header; typedef struct { unsigned short source;//porta sorgente unsigned short dest;//porta destinazione unsigned int seq;//numero della sequenza unsigned int ack_seq;//numero di Acnowledge unsigned char unused;//non utilizzato unsigned char doff:4;offset dei dati ;) //Se avete una macchina "Big Endian" invertite i due campi precedenti unsigned char flags;//flags TCP unsigned short checksum;//checksum pacchetto TCP unsigned short urg_ptr;//urgent Pointer TCP_Header; Queste due strutture, le inseriremo in un file header che poi importeremo all interno del nostro codice. Chiamatelo inet structures.h. Ed ora iniziamo a dare un occhiata al codice e a commentarlo (non spaventatevi! ;) ) riga per riga, il codice completo lo trovate alla fine: #include <stdio.h> Questa include e per le funzioni di i/o #include <sys/socket.h> Senza questa le socket ve le scordate ;) #include <sys/ioctl.h> Questa ci serve per poter utilizzare la funzione ioctl(). #include <net/if.h> Funzioni per accedere alle interfacce. #include <netinet/in.h> Strutture necessarie all utilizzo delle socket #include <arpa/inet.h> Contiene funzioni per fare conversioni da network a host byte order.vi ricordate little/big Endian? no? leggetevi lo Stevens!! #include <unistd.h> #include "inet_structures.h" Questa e la nostra libreria contenente le nostre strutture. #define IFACE "eth0" Interfaccia sulla quale vogliamo effettuare lo sniffing. 2

int sock, bytes_received, fromlen; In sock verra salvato il file descriptor della connessione (ricordatevi che in Unix le socket vengono viste come file particolari), mentre Bytes received, verra utilizzata come buffer per il salvataggio dei bytes ricevuti(ho detto ricevuti e non letti!). fromlen viene utilizzata come variabile d appoggio per salvare la dimensione della struttura sockaddr in. char buffer[65535]; Buffer utilizzato per salvare i byte letti dalla socket. struct sockaddr from; struct IP_Header *ip; struct TCP_Header *tcp; Queste sono le strutture che utiliziamo. Inet_SetPromisc(IFACE); Questa e la funzione che utiliziamo per aprire la socket e per settare l interfaccia in modalita promiscua. La modalita promiscua ci serve per poter analizzare tutti i pacchetti che viaggiano sulla nostra Lan locale, in pratica la nostra scheda di rete cattura anche i pacchetti con indirizzo MAC diverso dal proprio. Ovviamente saranno visibili solo i pacchetti che viaggiano sul nostro stesso segmento di rete, unico modo per vedere anche pacchetti su altri segmenti e utilizzare l arp poisoning, in questo modo la nostra scheda si identifichera come destinatario dei paccheti degli altri host nella loro arp cache. sock = Inet_SetPromisc(IFACE); Serve a creare la socket e a mettere in promiscuo la scheda, la funzione ve la spiego in dettaglio piu avanti. while(1) { In questo modo lo sniffer analizza in modo continuo i pacchetti. fromlen = sizeof(from); dimensione della strutura sockaddr in. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen); int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen); Con questa chiamata, ci ritroveremo ad avere la struttura from riempita con tutti i dati della macchina da cui il pacchetto proviene. printf("\nbytes received ::: %5d\n",bytes_recieved); 3

recvfrom() restituisce il numero di byte che riesce a leggere dalla socket o -1 in caso di errore printf("source address ::: %s\n",inet_ntoa(from.sin_addr)); Stampo l IP sorgente del pacchetto. ip = (struct ip *)buffer; //Guardo se e un paccheto TCP if(ip->proto == 6) { printf("lunghezza Header = %d\n",ip->h_len); printf("protocollo = %d\n",ip->proto); tcp = (struct tcp *)(buffer + (4*ip->h_len)); printf("porta Sorgente = %d\n",ntohs(tcp->source)); printf("porta Destinazione = %d\n",ntohs(tcp->dest)); Analizzo l header IP e stampo le informazioni a video. int Inet_OpenRawSock() { int sock; if((sock = socket(af_inet, SOCK_RAW, IPPROTO_TCP)) < 0) { perror("errore creazione socket"); exit(0); ; return(sock); Con questa funzione creiamo la nostra socket in modalita raw e con protocollo TCP. int socket(int domain, int type, int protocol); Alla funzione socket() che si occupa di definire il protocollo vengono passati tre parametri : domain : Definisce un dominio di comunicazione,ovvero la famiglia del protocollo che sara usato per la comunicazione. PF_INET : ipv4 protocollo internet PF_INET6 : ipv6 protocollo internet PF_UNIX : Comunicazione locale PF_NS : Protocolli di Xerox NS PF_IMPLINK : Livello di collegamento IMP *PF (protocol family) e AF (address family) sono equivalenti. type : Indica il tipo di socket SOCK_STREAM : streaming connection (TCP) SOCK_DGRAM : datagram communication (UDP) SOCK_RAW : Accesso "grezzo" al protocollo di rete (IP) protocol : Indica il particolare protocollo utilizzato dal socket0 : il sistema usa il protocollo piu adatto al tipo di socket IPPROTO_UDP : udp IPPROTO_TCP : tcp IPPROTO_ICMP : icmp IPPROTO_RAW : ip 4

int Inet_SetPromisc(char *iface, int sock ) { int sock; struct ifreq ifr; sock = Inet_OpenRawSock(iface); memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); if((ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)) { perror("errore Interfaccia\n"); exit(0); printf("interfaccia: %s\n", iface); //Setto l interfaccia in modalita promiscua if (!(ifr.ifr_flags & IFF_PROMISC)) { ifr.ifr_flags = IFF_PROMISC; if ( ioctl(sock, SIOCSIFFLAGS, &ifr) < 0 ){ // promisc mode perror("errore non riesco a settare la modalita promiscua"); exit(0); printf("interfaccia %s settata in modo promiscuo", iface); return(sock); Questa funzione e il cuore del nostro programma, prende la nostra interfaccia di rete e la setta in modalita promiscua. ifr e la struttura tramite utilizzata dalla funzione ioctl per accedere ai parametri della nostra interfaccia. ioctl(sock, SIOCGIFFLAGS, &ifr) Con questa chiamata, andiamo a leggere quali sono tutti i parametri della nostra interfaccia, per poi poterli modificare. Il primo parametro e la socket su qui vogliamo lavorare, mentre il secondo e la richiesta che vogliamo efettuare, ifr ci serve per salvare i valori della ioctl. ifr.ifr_flags = IFF_PROMISC; Qui modifico i parametri dell interfaccia per poi renderli effettivi tramite la ioctl successiva. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) Questa seconda chiamata alla ioctl rende effettivi i parametri che ho modificato nella struttura ifr. 5

2 Codice Sniffer in C #include <stdio.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include "inet_structures.h" #define IFACE "eth0" //prototipi int Inet_OpenRawSock(void); int Inet_SetPromisc(char *iface); int main() { int sock, bytes_recieved, fromlen; char buffer[65535]; struct sockaddr from; IP_Header *ip; TCP_Header *tcp; //Creiamo la socket e mettiamola in promiscuo sock=inet_setpromisc(iface); while(1) { fromlen = sizeof from; bytes_recieved = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&from, &fromlen); if (bytes_recieved < 0){ printf("sock=%d",sock); perror("errore recv"); exit(1); printf("\nbytes received ::: %5d\n",bytes_recieved); //printf("source address ::: %s\n",inet_ntoa(from.sin_addr)); ip = (IP_Header *)buffer; //Guardo se e un paccheto TCP if(ip->proto == 6) { printf("lunghezza Header = %d\n",ip->h_len); printf("protocollo = %d\n",ip->proto); tcp = (TCP_Header *)(buffer + (4*ip->h_len)); printf("porta Sorgente = %d\n",ntohs(tcp->source)); printf("porta Destinazione = %d\n",ntohs(tcp->dest)); 6

int Inet_OpenRawSock() { int sock; if((sock = socket(af_inet, SOCK_RAW, IPPROTO_TCP)) < 0) { perror("errore creazione socket"); exit(0); ; return(sock); int Inet_SetPromisc(char *iface) { int sock; struct ifreq ifr; sock = Inet_OpenRawSock(); printf("sock promisc=%d",sock); memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); if((ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)) { perror("errore Interfaccia\n"); exit(0); printf("interfaccia: %s\n", iface); //Setto l interfaccia in modalita promiscua if (!(ifr.ifr_flags & IFF_PROMISC)) { ifr.ifr_flags = IFF_PROMISC; if ( ioctl(sock, SIOCSIFFLAGS, &ifr) < 0 ){ // promisc mode perror("errore non riesco a settare la modalita promiscua"); exit(0); printf("interfaccia %s settata in modo promiscuo", iface); return(sock); 3 Esempio di utilizzo Raw Sockets <Aspinall > /**************************************************************** * Copyright (c) 2003 * * author : <aspinall@oltrelinux.com> or <aspi@spine-group.org>* * send to host a rst flag with ip spoofed* * compile gcc spoof_tcp.c -o spoof_tcp * * Use : #./spoof_tcp 1.1.1.1 212.4.13.231 * 7

* License : This source file is under GPL * * Only for Linux kernel * * * * * * Special thanks to : #networking@azzurranet * * mydecay <mydecay@spine-group.org> * * sviat <l.pizzira@virgilio.it> * * This code is derived from my knowledge of raw sockets, * * due to lack of well-done documentation on the web. you * * can use it to forge your own tcp packets,all you ve got * * to do is change header to suit your needs. * * * * Disclaimer: * * Use of this information constitutes acceptance for use in * * an AS IS condition.there are NO warranties with regard to * * this information. In no event shall the author be liable for * * any damages whatsoever arising out of or in connection with * * the use or spread of this information. Any use of this * * information is at the user s own risk. * ****************************************************************/ #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <time.h> void send_rst(void); /* algoritmo del checksum */ unsigned short in_cksum(unsigned short *addr,int len) { int sum = 0; u_short answer = 0; u_short *w = addr; int nleft = len; while (nleft > 1) { sum += *w++; nleft -= 2; if (nleft == 1 ) { 8

*( u_char* ) ( &answer ) = *( u_char * )w; sum += answer; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return(answer); // main() main(int argc, char *argv[]) { struct pseudo_header { u_long saddr; u_long daddr; char useless; char protocol; u_short length; ; char buf[256], buf2[256]; struct hostent *host; struct hostent *host2; struct iphdr *ip = (struct iphdr *) buf; struct tcphdr *tcp = (struct tcphdr *) (buf + sizeof(struct iphdr)); struct pseudo_header *pseudo = (struct pseudo_header *)buf2; struct sockaddr_in addr; struct sockaddr_in addr2; int fd, on=1; if (geteuid ()) { fprintf (stderr, "You should be root\n"); exit (1); if (argc < 3) { printf("usage : <spoof_sorg> <host_dest> <port>\n"); exit(1); if ((host = gethostbyname(argv[1]))!= NULL) memcpy (&addr.sin_addr, host->h_addr, host->h_length); else if((addr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) { herror("gethostbyname"); 9

exit(1); if ((host2 = gethostbyname(argv[2]))!= NULL) memcpy (&addr2.sin_addr, host->h_addr, host->h_length); else if((addr2.sin_addr.s_addr = inet_addr(argv[2])) == INADDR_NONE) { herror("gethostbyname"); exit(1); if((fd = socket(pf_inet,sock_raw,ipproto_tcp)) < 0) { perror("socket"); exit(1); if(setsockopt(fd,ipproto_ip,ip_hdrincl,&on,sizeof(on)) < 0) { perror("setsockopt"); exit(1); /* memoria a 0 */ memset(ip, 0, sizeof(struct iphdr)); memset(tcp, 0, sizeof(struct tcphdr)); memset(pseudo, 0, sizeof(struct pseudo_header)); /* HEADER */ pseudo->saddr = inet_addr(argv[1]); /* sorgente */ pseudo->daddr = inet_addr(argv[2]); /* destinazione */ pseudo->useless = 0; /* inutile :P */ pseudo->protocol = IPPROTO_TCP; /* tcp */ pseudo->length = htons(sizeof(struct tcphdr)); /* lunghezza header */ ip->ihl = 5; ip->version = 4; ip->tos = 0; ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); ip->id = htons((u_short)random()); ip->frag_off = htons(ip_df); ip->ttl = 255; ip->protocol=ipproto_tcp; ip->saddr = addr.sin_addr.s_addr; ip->daddr = addr2.sin_addr.s_addr; ip->check = 0; tcp->source = htons(rand()); /* guardare sopra*/ tcp->dest = htons(atoi(argv[3])); /* guarda sopra */ tcp->seq = htonl(random()); /* dopo */ tcp->ack_seq = 0; /* dopo */ 10

tcp->doff = 5; /* offset */ tcp->fin = 0; tcp->syn = 0; tcp->rst = 1; tcp->psh = 0; tcp->ack = 0; tcp->urg = 0; tcp->window = htons(4000); tcp->urg_ptr = 0; tcp->check = 0; /* checksum */ memcpy(buf2, pseudo, sizeof(struct pseudo_header)); memcpy(buf2 + sizeof(struct pseudo_header), tcp, sizeof(struct tcphdr)); memset(buf2 + sizeof(struct pseudo_header) + sizeof(struct tcphdr), 0, 12); tcp->check = in_cksum((unsigned short *)buf2,(sizeof(struct pseudo_header) + sizeof(struct tcphdr) + 12 ip->check = in_cksum((unsigned short *)buf2,(sizeof(struct iphdr) + sizeof(struct tcphdr) + 12) & ~1); /* send */ addr.sin_family = AF_INET; addr.sin_addr.s_addr = addr2.sin_addr.s_addr; addr.sin_port = htons(7); if(sendto(fd,buf, ip->tot_len, 0,(struct sockaddr *)&addr, sizeof(addr)) < 0 ) { perror("sendto"); exit(1); printf("the ip header is %d bytes long.\n", sizeof(struct iphdr)); printf("the tcp header is %d bytes long.\n", sizeof(struct tcphdr)); printf("ip checksum correct\ntcp checksum correct\n"); printf("done\n"); return 0; 4 Ringraziamenti Eccovi i soliti noiosi ringraziamenti (mi costringono con la forza a farli!!) Un saluto a tutto il gruppo degli spine e ovviamente anche a tutti i ragazzi di #phrack.it;)...dimenticavo di salutare anche tutte le rosse con gli occhi verdi!! che vi credevate?che vivessi di sola informatica?:) Ovviamente saluto anche il miglior chan di Azzurra #networking. 11

References [1] W. Richard Stevens. The Protocols (TCP/IP Illustrated, Volume 1) Edition: Hardcover Stevens1 [2] W. Richard Stevens. T The Implementation (TCP/IP Illustrated, Volume 2) Edition: Hardcover Stevens1 12