Command disabled: backlink

zampa[at]autistici.org


echoIntelligenza e' la capacita' di evitare di fare un lavoro, ottenendo tuttavia di trovarlo finito» /dev/OpenSource

Costruzione di uno sniffer, cosa serve? bah…. poca robba un pc e un compilatore gcc.

Per la realizzazione di questo sniffer useremo le comodissime librerie pcap, prima di scrivere il codice, vediamo quelle che sono le funzioni messe a disposizione dalle pcap lib. Le principali funzioni di questa libreria permettono con una facilità estrema di cercare e trovare un device di rete, inteso come network adapter, impostarlo in modalità promiscua (in modo diverso rispetto alla chiamata ioctl()(man ioctl), gestire filtri potenti e flessibili, selezionare grazie ai filtri il traffico da analizzare, analizzare pacchetto per pacchetto. Permette inoltre un'ottima gestione degli errori, quindi un buon livello di debug.

Funzioni principali

char *pcap_lookupdev(char *errbuf);

La funzione pcap_lookupdev cerca e restituisce un puntatore con il primo device di rete che trova ovviamente si puo forzare il device che si vuole. L'argomento errbuf è semplicemente un buffer utilizzato per contenere errori.Ah se la parola puntatore vi lascia un pò così <gapil.truelite.it/index.html>

int pcap_lookupnet(char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);

La funzione pcap_lookupnet parla da se:),analizza il device è restituisce mask e network associati al device,bpf_u_int32 *netp e bpf_u_int32 *maskp sono i puntatori che indicano rispettivamente quando detto prima.

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *errbuf);

La funzione pcap_open_live serve per aprire ed impostare un device in modalità promiscua e restituisce un packet capture descriptor pcap_t *(puntatore a file), un descrittore che si utilizzerà per accedere al device. snaplen indica il valore massimo di byte da catturare, to_ms invece è un read timeout.

con queste prime funzioni si prepare l'host sniffing a masticare pachetti di un'intera lan su qualsiasi protocollo,porta e ip, per ottenere un filtraggio più dettagliato e mirato abbiamo le seguenti funzioni

int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask);

con questa funzione prepariamo il filtraggio specificando cosa filtrare in char *str, del tipo se assegnamo la stringa char *str=“tcp” filtreremo solo ciò che protocollo 6

int pcap_setfilter(pcap_t *p, struct bpf_program *fp);

La funzione pcap_setfilter imposta nella struttura bpf_program i filtri.Rendendo cosi effetive le impostazioni di filtraggio impostate con la funzione pcap_compile

int pcap_stats(pcap_t *p, struct pcap_stat *ps)

Molto utile per sapere quanti pachetti sono stati catturati quanto droppati dal kernel etc etc, per avere delle statistiche sul traffico in e out

void pcap_close(pcap_t *p)

I filtri sono una delle caratteristiche più interessanti ed efficaci che ci offre libpcap. pcap_compile e pcap_set_filter si appoggiano alla struttura bpf_program e compilano i filtri attraverso BPF. Berkeley Packet Filtering è una macchina virtuale gestita a livello del kernel che si divide in due componenti: network tap e packet filter. Network tap è un device che prende in consegna il pacchetto ed il packet filter si occupa di controllare eventuali restrizioni: se i filtri lo consentono BPF consegna il pacchetto al protocollo applicativo.

Abbiamo visto che i filtri vengono gestiti dalle pcap come semplici stringhe. Le espressioni per il matching dei pacchetti sono:

  • proto: protocollo;
  • dst host: host di destinazione;
  • dst net: network di destinazione;
  • dst port: porta di destinazione;
  • src host [host]: host sorgente;
  • src net: network sorgente;
  • src port: porta sorgente;
  • ”!” o “not”: matching inverso (negazione);
  • ”&&” o “and”: matching concatenato (entrambi i filtri devono essere soddisfatti);
  • “||” o “or”: matching alternato (almeno un filtro deve essere soddisfatto).

le pcap lib usano le System call socket (man socket),quindi quano si andrà a settare il promisc mode usando setsocketopt anzichè ioctl, il normale ifconfig che usa ioctl non noterà che il device è in promisc mode, ovviamente si puo sempre risalire a device in promisc mode, ma meno facilmente.

Costruiamo il nostro sniffing vediamo le strutture principali cominciamo con l'analizzare la struttura in main.h

 /**
  * @i32         bpf_int32 netmask
  * @i32         bpf_int32 address ip
  * @device      device name
  * @fd          file descriptor pcap session
  * upDevice     method invoca la funzione pcap_lookupdev
  * @setPromisc  method invoca pcap_open_live
  * @filterIn    method invoca pcap_compile
  * @filterSet   method invoca pcap_setfilter
  * @upNet       method invoca pcap_lookupnet
  * @start       method invoca pcap_loop
  * @stats       method invoca pcap_stat
  * @end         method invoca pcap_close
  */
 
 
 struct _sniff {
         i32 netmask;
         i32 network;
         char *device;
         pcap_t *fd;
         int snaplen;
         struct ethpacket packet;
         struct bpf_program fp;
         struct pcap_pkthdr hdr;
         char *(*upDevice)(char *);
         pcap_t * (*setPromisc)(char*);
         int (*filterIn)(void);
         int (*filterSet)(void);
         int (*upNet)(char *);
         int (*start)(pcap_handler);
         int (*stats)(struct pcap_stat *);
         void (*end)(void);
 }

con questa struttura creiamo una sorte di classe dove le varibili servono a memorizzare tutte le informazioni ricevute dalle chiamate alle funzioni libpcap, mentre i puntatori funzione lincano le funzioni della pcaplib direttamente, cosi avremò un'entità con tutte le informazioni relative al nostro device,rete,netmask etc, il tipo i32 è una (#define bpf_u_int32 i32).

La seconda entità è una struttura di controllo per la gestione della stampa, della selezione dei pachetti da catturare

control.h

....................
................
 /**
 * @packet              ethpacket
  * @iphdr               tmp header ip
  * @tcphdr              tmp header tcp
  * @store               method for store packet sniffed
  * @type_sniff          method for verify proto
  * @printf_header       method for print header
  * @print_data          method for print data
  */
 
 struct _control
 {
 struct ethpacket packet;
 struct iphdr *ip;
 struct tcphdr *tcp;
 void (*store)(u_char*);
 int  (*type_sniff)(int);
 void (*print_header)(void);
 void (*print_data)(void);
 };

queste strutture vengono inizzializzate in init.c, qui vengono lincate le funzioni richiamate nelle nostre entità

init.c

 void init_sniff(sniff *mySniff)
 {
        mySniff->network=0;
        mySniff->netmask=0;
        mySniff->snaplen=1024;
        memset(&mySniff->fp,0,sizeof(struct bpf_program));
        memset(&mySniff->hdr,0,sizeof(struct pcap_pkthdr));
        mySniff->upDevice=pcap_lookupdev;
        mySniff->setPromisc=setPromisc;
        mySniff->filterIn=filterIn;
        mySniff->filterSet=filterSet;
        mySniff->upNet=upNet;
        mySniff->start=start;
        mySniff->stats=stats;
        mySniff->end=end;
 
 
 }
 
void init_control(void)
{
        Control.print_header=print_header;
        Control.print_data=print_data;
        Control.type_sniff=type;
        Control.store=store;
        Control.ip=(struct iphdr *)((unsigned long)(&Control.packet.ip)-2);
        Control.tcp=(struct tcphdr *)((unsigned long)(&Control.packet.tcp)-2);
}

Per tener traccia di tutte le connessioni che andiamo a sniffare, usiamo una lista, per la creazione e la gestione delle liste usiamo le librerie GLIB, nel source user_speak.h dichiariamo tutti i prototipi di funzione

user_speak.h

struct _dhost
{
        unsigned long int saddr;
        unsigned long int daddr;
        unsigned short int sport;
        unsigned short int dport;
        int connect;
};
 
typedef struct _dhost dhost;
 
dhost *create(unsigned long int,unsigned long int,unsigned short int,unsigned short int,int);
static gint list_compare(dhost*,dhost*);
GList *insert(dhost *);
GList *remove_host(dhost *);
GList *find(dhost *);
void freehost(void);

……………………………da completare———- qui i sorgenti completi download sniff.tar.gz _sniff

acari/zampa.txt · Ultima modifica: 2012/10/05 22:27 (modifica esterna)
Creative Commons License Driven by DokuWiki Valid XHTML 1.0