Programmare con le Raw Socket

2002-04-25

When I was 16, I used to write articles under the nicknames Esorcista and XpTerminator.

The following is an article I translated from English to Italian, that got published on the 7th issue of OndaQuadra, an Italian e-zine.

+--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | PR0GRAMMARE LE REW S0CKET (TRADUZi0NE) [XpTerminator] 0x11/0x1D | +--------------------------------------------------------------------------+ | | | -==============================- | | | Programmare le raw socket | | | | Nitr0gen | | | =/____________________________\= | | | traduzione by XpTerminator | | | -==============================- | | | | Premetto innanzi tutto che questo testo non e` di mia fattura, io ho | | effettuato la traduzione dalla lingua inglese e delle modifiche ed | | aggiunte per rendere il testo più chiaro; visto che in lingua | | italiana non si trovano documenti del genere, ed essendo | | interessante, ho ritenuto utile effettuarne la traduzione. | | | | Exile 2000 International Coding Team | | (http://www.exile2k.org) | | Documentation about native raw socket programming | | All rights reserved Exile Team | | | | Free to distribute this text just keep it's integrity | | Ripping is lame remember this | | | | | | Per domande e commenti: (in english! ;) | | | | Nitr0gen | | nitr0gen@hackersnews.com | | | | oppure: (in italiano:) | | | | XpTerminator | | xp_terminator@katamail.com | | | | | | | | -----[ Prefazione ]--- | | | | | | A differenza di come pensano molte persone, | | programmare le raw socket non è annoiante ed una | | perdita di tempo, anzi è una buona esperienza per | | imparare ed a volte è molto utile. Programmando le | | raw socket si ha molta più flessibilità rispetto ai | | programmi che utilizzano socket con librerie standard | | e quindi diventa facile implementare nuovi protocolli | | e controllare cosa sta realmente accadendo anche al | | più basso dei livelli. | | Costruire pacchetti tramite una libreria è efficiente, | | ma immagina quanto lo sia tramite una TUA libreria. | | Non mi trovo qui per spiegare quanto sia figo o | | potente programmare le raw socket, quindi vado | | direttamente al dunque. Prima di tutto, voglio | | avvertire che per poter comprendere al meglio questo | | testo bisogna avere una buona conoscenza del C e della | | struttura della rete. | | Nella prima parte del testo introdurrò l'header ip, | | l'header tcp, quello udp ed infine quello icmp, ultimo | | non per importanza. | | | | La seconda parte di questa prefazione è dedicata ai | | lamer: per favore abbiate rispetto dell'autore del | | testo (Nitr0gen) e non rippate queso testo per vostri | | scopi! | | | | Nitr0gen and Exile 2000 International Coding Team: | | don't worry! i've only translated your document, | | and i've riported this! | | | | | | | | | | | | | | -----[ Indice ]--- | | | | | | | | | | [ Header Ip ] | | - Teoria | | - Frammentazione | | - Checksum | | - Esempi | | | | [ Header Tcp ] | | - Teoria | | - Esempi | | | | [ Header Udp ] | | - Teoria | | - Esempi | | | | [ Header Icmp ] | | - Teoria | | - Esempi | | | | [ Implementazione ] | | | | [ Conclusioni ] | | | | [ Appendice A ] | | - Strutture e Funzioni | | - Codici sorgente | | | | [ Riferimenti ] | | | | [ Ringraziamenti ] | | | | | | | | | | [ CAPITOLO 1 ] | | (HEADER IP) | | | | | | ---[ Teoria | | | | | | Bene, se sei interessato nella programmazione delle | | raw socket presumo che tu conosca le basi del tcp/ip. | | L'header IP fa parte del layer di rete della suite di | | protocolli tcp/ip. Fondamentalmente l'header ip è usato | | per routare i pacchetti attraverso una rete,come internet | | una wan o una lan. Il metodo di trasmissione di questo | | header è inaffidabile poichè non hai garanzia dell'arrivo | | a destinazione del pacchetto, o meglio, quando invii | | dei pacchetti, non hai la certezza che questi arrivino a | | destinazione nel giusto ordine in cui li hai inviati. | | Prendi per esempio i pacchetti A B. A viene inviato prima | | di B, ma non è garantito che A prenderà la stessa strada | | (routing) di B per arrivare a destinazione. Il risultato | | di ciò è quello che ho detto prima, i pacchetti non | | vengono ricevuti nello stesso ordine di partenza. Come ho | | ho detto dalla partenza, questo testo non è un corso di | | tcp/ip ma un testo sulla programmazione, quindi, mi | | limiterò alla programmazione. A titolo di informazione, | | quando costruisci un pacchetto non dimenticare htons() o | | htonl() per rispettare il giusto ordine dei byte. | | Dei lettori si staranno sicuramente chiedendo perchè sto | | dicendo questo, rispondo dicendo che io ho passato un | | mese per risolvere questo piccolo problema. | | | | | | | | | | Questa è una rappresentazione ascii dell'header ip: | | | | | | 0 15-16 31 | | +-----+-----+-----------+-----------------------+ \ | | | Ver | IHL | TOS | Total Length | \ | | | (4) | (4) | (8) | (16 ) | | | | +-----+-----+-----------+--------+--------------+ | | | | Identification | Flags | Frag Offset | | | | | (16) | (3) | (13) | | | | +-----------+-----------+--------+--------------+ | | | | TTL | Protocol | Header Checksum | 20 Bytes | | | (8) | (8) | (16) | | | | +-----------+-----------+-----------------------+ | | | | Source Ip Address | | | | | (32) | | | | +-----------------------------------------------+ | | | | Destination Ip Address | | | | | (32) | / | | +-----------------------------------------------+ / | | < Options > | | > (if any) < | | +-----------------------------------------------+ | | > < | | < Data > | | > < | | | | | | | | Version (4 bits): | | Il campo version è usato per indicare la | | versione del IP (Internet Protocol), quindi o IpV4 | | o IpV6. | | | | | | IHL (Internet Header Length, 4 bits): | | Il campo ihl indica la lunghezza dell'header | | Ip. Quando non si usano opzioni, il valore di default | | dovrebbe essere 5. | | | | | | TOS (Type Of Service, 8 bits): | | Tos è utilizzato per specificare le necessità | | del servizio. | | | | Vi sono 4 opzioni per TOS: | | | | *NOME* *Valore esadecimale* | | | | 1- Minimize delay 0x10 | | 2- Maximize throughput 0x08 | | 3- Maximize reliability 0x04 | | 4- Minimize monatary cost 0x02 | | | | 1: Questa opzione è utilizzata da applicazioni | | che trasmettono piccole quantità di dati e | | necessitano di una risposta veloce. | | | | 2: Caso opposto: questo è usato da applicazioni | | che trasmettono grandi quantità di dati. | | | | 3: Non ne parlerò in questo testo. | | | | 4: Non ne parlerò in questo testo. | | | | Dato che TOS è una caratteristica sperimentale | | dell'ip, non ci dilungheremo su di esso in questo | | testo. | | | | | | Total Length (8 bits): | | Questo specifica la grandezza del datagramma, | | (header + dati). Per esempio: | | Prendiamo un pacchetto (ip header + tcp header[syn]) | | senza dati. La grandezza dell'header ip è 20 e quella | | dell'header tcp anche, quindi il campo tot_len sarà 40. | | | | | | Identification (16 bits): | | Id è utilizzato per identificare i frammenti. | | Quando un pacchetto non è frammentato questo campo | | è inutile. L'Id solitamente aumenta da datagramma a | | datagramma; ogni frammento ha lo stesso id del | | datagramma a cui appartiene. | | | | | | Flags (3 bits): | | Questo campo dell'header ip è utilizzato dalla | | frammentazione. Ci sono 4 flag: | | | | *NOME* *Valore esadecimale* | | | | No flags 0x00 | | More fragment 0x01 | | Don't fragment 0x02 | | More and Dont't frag 0x03 | | | | More fragment significa che ci sono ancora frammenti | | dopo questo datagramma, don't fragment dice che il | | pacchetto non è frammentato. Quando un datagramma è | | frammentato,l'ultimo frammento non ha mai il flag MF | | (More Fragment) settato. | | | | | | Fragment Offset (13 bits): | | Questo è l'offset con il quale il pacchetto | | è stato calcolato. Il primo datagramma ha offset 0. | | Questo campo è calcolato a 64 bits. Quando si calcola | | l'offset, l'ultimo offset sarà uguale a tot_len. | | | | | | TTL (Time To Live, 8 bits): | | Questo campo specifica quanti hop potrà | | effettuare il datagramma. Esso è decrementato ogni | | volta che viene rispedito (durante il routing: ogni | | router decrementa di 1 questo valore). Quando il TTL | | raggiunge 0, il datagramma viene ignorato e viene | | inviato al mittente un messaggio icmp di TIME EXCEED. | | Questo avviene per evitare che un datagramma giri | | all'infinito per la rete. | | | | | | Protocol (8 bits): | | Questo campo specifica il protocollo per il | | layer di trasmissione. Il valore può essere: | | | | *NOME* *Valore esadecimale* | | | | IPPROTO_TCP 0x06 | | IPPROTO_UDP 0x11 | | IPPROTO_ICMP 0x01 | | | | Vi sono anche altri protocolli ma non saranno trattati | | in questo testo. Per maggiori informazioni osserva il | | seguente file header che definisce tutte le costanti. | | '/usr/include/linux/in.h' | | | | | | Header CheckSum (16 bits): | | Il checksum è utilizzato per verificare | | l'integrità di un datagramma. Se i dati durante | | il trasporto si sono corrotti o modificati,esso | | è in grado di capirlo. Se il checksum non viene | | specificato nel datagramma, questo viene | | scartato senza alcun tipo di avvertenza. Dal | | punto di vista del programmatore ciò risulta | | annoiante.Osserva l'appendice A per la funzione | | del checksum ( in_cksum() ). | | | | | | Source Ip (32 bits): | | L'indirizzo ip dell'host che ha inviato il | | datagramma. | | | | Destination Ip (32 bits): | | L'indirizzo ip della macchina a cui dovrà | | essere "recapitato" questo datagramma. | | | | | | Options (Variable): | | Il campo options non sarà trattato in | | questo testo. | | | | | | | | Dal punto di vista della programmazione, costruire | | un header ip significa semplicemente riempire una struttura. | | Dato che sto utilizzando Linux, tutti i riferimenti che farò | | a file di sistema saranno basati su kernel 2.2.13. | | | | | | | | | | ---[ Frammentazione | | | | | | In parole povere, la frammentazione avviene | | quando il MTU (Maximum Transfert Unit) è minore della | | lunghezza totale del datagramma, quindi, dovremo | | dividere il datagramma in piccoli pezzi, ed inviarli | | uno alla volta; quando i pacchetti saranno ricevuti, | | il datagramma originale sarà ricostruito. | | Quando effettuiamo la frammentazione,abbiamo bisogno di | | settare campi specifici dell'header Ip. | | Il flag MF deve essere settato a tutti i frammenti, | | tranne l'ultimo.L'offset del primo pacchetto sarà zero. | | L'Id dovrà essere lo stesso per ogni frammento, per | | identificare a quale serie di pezzi di datagramma | | appartiene.Se l'header Ip è modificato anche in un solo | | frammento il checksum dovrà essere ricalcolato. La | | lunghezza totale dei frammenti prenderà il valore del | | MTU. | | | | | | | | | | ---[ Checksum | | | | | | Calcolare il checksum di un header non è | | difficile, osserva l'appendice A per vedere la funzione | | responsabile di questa operazione. | | Questo è il prototipo della funzione: | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | - unsigned short *addr : E' un puntatore all'header ip. | | - int len : E' la lunghezza dell'header ip. | | | | | | | | | | | | | | | | ---[ Esempi | | | | | | Il nome della sezione dice esplicitamente cosa | | troverai qui. | | | | | | | | /*******************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header IP */ | | /* SENZA FRAMMENTAZIONE */ | | /* */ | | /*******************************************************************/ | | | | void buildip_nf(){ /*** Funzione che costruisce un Header Ip ***/ | | | | struct iphdr *ip; | | /*** A little step for a man, a big step for human kind ***/ | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | /*** Alloca la memoria dinamica ***/ | | | | ip->ihl = 5; /*** Lunghezza in byte dell'Header IP ***/ | | ip->version = 4; /*** Versione del protocollo IP ***/ | | ip->tos = 0; /*** Sperimentale (Vedi sopra per i dettagli) ***/ | | ip->tot_len = sizeof(struct iphdr) + 452 /*** Lunghezza totale del ***/ | | /*** pacchetto ***/ | | | | | | ip->id = htons(getuid()); | | /*** ID (identification) del pacchetto, inutile nel nostro caso ***/ | | | | ip->ttl = 255; /*** Il pacchetto può effettuare | | 255 hop ***/ | | ip->protocol = IPPROTO_TCP; /*** Utilizziamo il tcp come protocollo | | di trasmissione ***/ | | ip->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente ***/ | | ip->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione ***/ | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | /*** Checksum ***/ | | | | } | | | | | | | | | | /*****************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header IP */ | | /* FRAMMENTAZIONE del pacchetto */ | | /* in 2 frammenti */ | | /* MTU = 280 byte */ | | /* */ | | /*****************************************************************/ | | | | | | | | void buildip_f(){ | | /*** Funzione che costruisce un header IP frammentato ***/ | | | | struct iphdr *ipf; | | | | ipf = (struct iphdr *) malloc(sizeof(struct iphdr)); | | | | /**** PRIMO FRAMMENTO ***/ | | ipf->ihl = 5; /*** Lunghezza dell'header in 32 bit */ | | ipf->version = 4; /*** Versione del protocollo IP */ | | ipf->tos = 0; /*** TOS (Type of service), inutilizzato */ | | ipf->tot_len = sizeof(struct iphdr) + 256; /* Lunghezza del | | primo frammento */ | | ipf->id = htons(1); /*** Per identificare i nostri 2 frammenti */ | | ipf->ttl = 255; /*** Il datagramma può effettuare 255 hop */ | | ipf->protocol = IPPROTO_TCP; /*** uso il protocollo TCP */ | | ipf->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente (localhost) */ | | ipf->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione | | (localhost) */ | | ipf->frag_off = htons(0x2000); /*** Offset 0 e MF */ | | ipf->check = in_cksum((unsigned short *)ipf,sizeof(struct iphdr)+256); | | /*** Checksum */ | | | | | | /**** Qui dovremmo inviare il primo frammento ***/ | | | | | | /**** SECONDO FRAMMENTO ***/ | | ipf->tot_len = sizeof(struct iphdr) + 196; /*** Aggiorno la lunghezza | | dei datagrammi */ | | ipf->frag_off = htons(32); /*** Offset del frammento ***/ | | ipf->check = in_cksum((unsigned short *)ipf,sizeof(struct iphdr)+196); | | /*** Ricalcoliamo il checksum dato che abbiamo cambiato dei campi */ | | | | /**** Qui dovremmo inviare il secondo frammento ***/ | | | | } | | | | | | [ CAPITOLO 2 ] | | (HEADER TCP) | | | | | | | | | | ---[ Teoria | | | | | | Diamo ora un'occhiata all'header tcp. Dato | | he esso fa utilizzo di un metodo di trasmissione | | ffidabile, prima di effettuare lo streaming dei | | ati c'è bisogno di creare una connessione. Quindi, | | os'è una connessione? Con il tcp noi la chiamiamo | | hree-way-handshake ("stretta di mano" in tre fasi). | | on il primo passo il client invia al server un | | acchetto tcp SYN per sincronizzare (SYNchronize) | | l numero di acknowledgment; con il secondo passo | | l server "riconosce" (ACKnowledge) il syn, cioè | | onferma la sua ricezione, tramite un pacchetto | | YN_ACK. Se il SYN_ACK non è ricevuto dal client lo | | tato della connessione tcp rimane in SYN_SENT e | | l client continua l'invio di SYN al server, | | inchè esso non lo riceverà e quindi confermerà | | on SYN_ACK.Dopo la conferma dell'avvenuta ricezione | | el SYN, il client risponde con un ACK per | | onfermare l'avvenuta ricezione del SYN_ACK. | | eoricamente una connessione è creata tra due host, | | a se il server si disconnette prima di ricevere il | | ostro ultimo pacchetto (ACK), noi crederemo di | | ssere connessi, ma in realtà non lo siamo. Questo è | | no dei problemi del tcp. Il Tcp (Transfer control | | rotocol) come l'Ip ( Internet protocol ) ha un | | hecksum per il controllo dell'integrità dei dati | | he fa utilizzo di uno pseudo-header di cui | | arleremo dopo. Per essere sicuri che un pacchetto | | rovenga realmente dal source ip specificato nel | | uo header, il tcp ha aggiunto la funzionalità di un | | equence number, ciò significa che durante | | 'handshake, prima il client invia un Seq Number,poi | | l server effettua l'acknowledgement del SYN con il | | roprio seq number. Il server attende nel successivo | | acchetto del client il seq number come specificato | | el campo ACK dell'ultimo pacchetto inviato. Ciò | | reviene l'hijacking o lo spoofing di una | | onnessione da parte di utenti malintenzionati. | | cco un esempio: | | | | Host A < ---- TCP CONNECTION ----> HOST B | | | | ^---- HOST X (utente malintenzionato) | | | | Se non ci fosse il sequence number, HOST X | | potrebbe inviare pacchetti a HOST B facendo | | credere in realtà che questi provenghino da | | HOST A. Oggi giorno, con la generazione del | | sequence number ormai casuale questa tecnica è | | quasi impossibile. | | | | uesto protocollo ha ancora altre opzioni in ambito | | i sicurezza aggiunte a quelle dell'IP, ma non | | erranno trattate in questo testo. Il Tcp permette | | noltre un buon managing dei pacchetti in entrata | | d in uscita. Grazie alla specifica nei pacchetti | | elle porte sorgente e destinazione, molti processi | | ossono comunicare contemporaneamente. Tutte queste | | pzioni, incluse quelle non trattate, però hanno lo | | vantaggio di diminuire la velocità di trasmissione. | | i sei mai domandato cosa sia un socket? Il termine | | ocket nel mondo tcp è usato spesso. Questo è | | emplicemente un indirizzo ip combinato con un numero | | i porta, ed una coppia di socket è la combinazione | | ndirizzo Ip Sorgente + Porta Sorgente + Indirizzo Ip | | i Destinazione + Porta di Destinazione. | | | | Il Tcp ha 6 funzioni principali: | | | | | | URG: Invia dei dati urgenti, cioè con | | maggiore priorità, all'host di | | destinazione. | | | | ACK: "Acknowledgement" dei dati ricevuti. | | Come visto sopra. | | | | PSH: Invia i dati all'host di destinazione. | | | | RST: Resetta una connessione. | | | | SYN: Sincronizza il Seq Number. | | | | FIN: Nessun altro dato da inviare da parte | | dell'host. | | | | | | | | | | | | | | | | | | chema dell'header TCP: | | | | 15-16 31 | | -----------------------+-----------------------+ \ | | Source Port | Destination Port | \ | | (16b) | (16b) | | | | -----------------------+-----------------------+ | | | Sequence Number | | | | (32b) | | | | -----------------------------------------------+ | | | Acknowledgement | | | | (32b) | | | | -------+------+--------+-----------------------+ 20 Bytes | | D_Off | Res | Flags | Windows | | | | (4b) | (6b) | (6b) | (16b) | | | | -------+------+--------+-----------------------+ | | | Checksum | Urgent Pointer | | | | (16b) | (16b) | | | | -----------------------+------------+----------+ | | | Options | Padding | | | | (24b) | (8b) | / | | ------------------------------------+----------+ / | | DATA < | | > | | | | | | | | | | ource Port (16 bits): | | La porta sorgente del pacchetto. | | I pacchetti di ritorno saranno ricevuti su | | questa porta. | | | | estination Port (16 bits): | | La porta di destinazione del | | pacchetto. Il pacchetto sarà ricevuto su | | questa porta dall'host di destinazione. | | | | equence number (32bits): | | Il Sequence number è una buona | | caratteristica della sicurezza del tcp. | | Quando un pacchetto viene ricevuto, il | | modulo tcp del kernel verifica se il | | numero è giusto. Se non lo è, il | | pacchetto viene scartato. | | | | | | | | cknowledgment (32 bits): | | Quando il flag ACK è settato, il | | valore di questo campo è settato al | | valore del Seq number che ci si aspetta | | di ricevere nel prossimo pacchetto da | | parte dell'altro peer (capo della | | connessione). | | | | | | ata Offset (4 bits): | | L'offset dei dati espresso a 32 | | bit. Se non vi sono opzioni, il valore di | | default è 5. | | | | | | eserved (6 bits): | | Riservato per un uso futuro, deve | | essere settato a 0. | | | | lags (6 bits): | | Ci sono 6 flag possibili nel tcp. | | Come visto sopra, questi sono: | | | | | | URG: Indicatore di urgenza | | ACK: Acknowledge | | PSH: Push | | RST: Reset | | SYN: Sincronizza il Seq Number | | FIN: Nessun altro dato da inviare | | | | | | indows (16 bits): | | Questo specifica il MSS (maximum | | segment size) del prossimo pacchetto. Se un | | pacchetto supera questo valore, esso dovrà | | essere frammentato. | | | | | | hecksum (16 bits): | | Il checksum per verificare | | l'integrità dei dati.Il checksum è calcolato | | con uno Pseudo-Header che spiegherò. Questa | | è la struttura, tratta da Tcp/Ip Volume 1 | | (The protocol) di W. Richard Stevens. Per | | favore dedica un minuto di silenzio per | | questo incredibile uomo che è morto, è stato | | uno straordinario scrittore. | | | | Questa è la struttura: | | | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }; | | | | L'header contiene l'indirizzo ip sorgente e | | destinazione per evitare pacchetti mal-routati | | (saddr, daddr). Il carattere "useless" esiste | | solo per rispettare il limite dei 32 bit | | (per questo "useless" = "inutile"). "protocol" | | contiene il protocollo, in questo caso | | IPPROTO_TCP, e "lenght", la lunghezza del | | pacchetto. | | | | Il checksum è calcolato come per l'header Ip: | | | | | | -------------- CUT HERE ----------------- | | | | #define PSEUDO sizeof(struct pseudohdr) | | #define TCPHDR sizeof(struct tcphdr) | | | | struct pseudohdr pseudo; | | struct tcphdr tcp; | | | | pseudo.saddr = inet_addr("127.0.0.1"); | | pseudo.daddr = inet_addr("127.0.0.1"); | | pseudo.useless = htons(0); | | pseudo.protocol = IPPROTO_TCP; | | pseudo.length = TCPHDR + data; | | | | tcp->check = in_cksum((unsigned short *)&pseudo, PSEUDO+TCPHDR); | | | | -------------- CUT HERE ---------------- | | | | | | | | Urgent Pointer (16 bits): | | Questo campo è significante solo se il flag | | URG è settato. Esso punta ad un'area dati e ciò | | rende i dati urgenti dal punto di vista dei peer. | | | | | | Options (24 bits): | | Il campo options non verrà trattato in | | questo testo. | | | | | | Padding (8 bits): | | Il campo padding è riempito con 0. Questo | | avviene per rispettare il limite dei 32 bit: esso | | parte con 32 bit e finisce con 32 bit. | | | | | | ---[ Esempi | | | | | | | | /******************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header TCP */ | | /* col flag SYN settato */ | | /* e richiede una connessione telnet su localhost */ | | /* */ | | /******************************************************************/ | | | | | | | | | | #define TCPHDR sizeof(struct tcphdr) | | #define PSEUHDR sizeof(struct iphdr) | | | | | | void build_tcp(){ | | | | struct tcphdr *tcp; /*** Header tcp ***/ | | struct pseudohdr *pseudo; /*** Pseudo header ***/ | | | | if ((tcp = (struct tcphdr *) malloc(TCPHDR)) == NULL){ | | perror("malloc()"); /*** Alloca la memoria dinamica ***/ | | return -1; | | } | | | | if ((pseudo = (struct pseudohdr *) malloc(PSEUDOHDR)) == NULL){ | | perror("malloc()"); /*** Alloca la memoria dinamica ***/ | | return -1; | | } | | | | memset(tcp,'\0',TCPHDR); /*** Inizializza la memoria | | al carattere \0 ***/ | | memset(pseudo,'\0',PSEUDOHDR); | | | | | | pseudo->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente ***/ | | pseudo->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione ***/ | | pseudo->useless = 0; /*** Spazio riservato per rispettare il | | limite ***/ | | pseudo->protocol = IPPROTO_TCP; /*** Utilizziamo tcp ***/ | | pseudo->length = htons(TCPHDR); /*** Dato che non abbiamo nessun | | dato, la lunghezza è solo | | quella dell'header tcp. ***/ | | | | | | tcp->source = htons(5000); /*** Utilizziamo la 5000 | | come porta sorgente ***/ | | tcp->dest = htons(23); /*** Inviamo al demone telnet ***/ | | tcp->seq = htonl(31337); /*** Initial sequence number ***/ | | tcp->ack_seq = htonl(0); /*** E' significante solo se è settato | | il flag ack ***/ | | tcp->doff = 5; /*** Offset dell'header tcp a 32 bit ***/ | | tcp->fin = 0; /*** Flag FIN non settato durante l'handshake ***/ | | tcp->syn = 1; /*** Flag SYN settato, primo passo dell'handshake ***/ | | tcp->rst = 0; /*** Flag RST non settato durante l'handshake ***/ | | tcp->psh = 0; /*** Flag PSH non settato durante l'handshake ***/ | | tcp->ack = 0; /*** Flag ACK non settato durante l'handshake ***/ | | tcp->urg = 0; /*** Flag URG non settato durante l'handshake ***/ | | tcp->window = htons(4000); /*** Lunghezza massima del prossimo | | pacchetto ***/ | | tcp->urg_ptr = htons(0); /*** E' significativo solo se il flag URG | | è settato ***/ | | | | tcp->check = in_cksum((unsigned short *)pseudo,TCPHDR+PSEUDOHDR); | | /*** Calcolo del checksum tcp per evitare corruzione dei dati ***/ | | } | | | | | | | | | | | | | | [ CAPITOLO 3 ] | | (HEADER UDP) | | | | | | | | | | ---[ Teoria | | | | | | Arrivato fin qui, hai superato la parte più | | "difficile". | | L'Udp è meno complesso del tcp. Esso non ha | | caratteristiche di sicurezza e neanche di affidabilità | | ma ha un maggiore transfert rate che lo rende utile. | | Come il tcp, anche l'udp ha un checksum ed ha bisogno | | di uno pseudo header per calcolarlo. | | | | | | Schema dell'Header UDP: | | | | | | 0 15-16 31 | | +-----------------------+-----------------------+ | | | Source Port | Destination Port | | | | (16 b) | (16 b) | | | +-----------------------+-----------------------+ | | | Length | Checksum | | | | (16 b) | (16 b) | | | +-----------------------+-----------------------+ | | > DATA < | | < > | | | | | | | | Source Port (16 bits): | | La porta sorgente del datagramma. | | I pacchetti di ritorno saranno ricevuti su | | questa porta. | | | | | | Destination Port (16 bits): | | La porta destinazione del datagramma. | | Il datagramma sarà ricevuto dal peer di | | destinazione su questa porta. | | | | | | Length (16 bits): | | Contiene la lunghezza dei datagrammi | | udp in ottetti, solitamente 8. | | | | | | Checksum (16 bits): | | Contiene il checksum del datagramma | | per controllarne l'integrità e per | | assicurare che non vi sono stati errori nel | | routing. | | | | Se sei curioso circa la sua struttura, | | osserva l'appendice A. | | | | | | | | | | | | ---[ Esempi | | | | | | | | | | /****************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header UDP */ | | /* */ | | /****************************************************************/ | | | | | | void build_udp(){ | | | | struct udphdr *udp; /*** Dichiarazione delle variabili ***/ | | struct pseudohdr pseudo; | | | | if ((udp = (struct udphdr *) malloc(sizeof(struct udphdr))) == NULL){ | | perror("Memory exhausted"); /*** Allocazione memoria | | dinamica ***/ | | return ; | | } | | | | | | /*** Pseudo-Header, utilizzato per evitare datagrammi "mal-routati" ***/ | | | | pseudo.saddr = inet_addr("127.0.0.1"); /* Inviamo da localhost **/ | | pseudo.daddr = inet_addr("127.0.0.1"); /* Inviamo a localhost **/ | | pseudo.useless = htons(0); /* Per rispettare il limite | | di 32 bit*/ | | pseudo.protocol = IPPROTO_UDP; /* Utilizziamo il protocollo UDP */ | | pseudo.length = sizeof(struct udphdr); /* sizeof della | | struttura udphdr */ | | | | udp->source = htons(5000); /** Inviamo dalla porta 5000 */ | | udp->dest = htons(7); /** Inviamo al server echo (porta=7) */ | | udp->len = htons(sizeof(struct udphdr)); /* Lunghezza di udphdr. | | Utilizziamo htons() | | per il giusto | | ordinamento dei byte */ | | | | udp->check = in_cksum((unsigned short *)&pseudo,sizeof(struct udphdr)); | | /*** Calcoliamo il checksum ***/ | | | | } | | | | | | [ CAPITOLO 4 ] | | (HEADER ICMP) | | | | | | | | | | ---[ Teoria | | | | | | Fondamentalmente l'Internet Control Message | | Protocol (ICMP) è utilizzato per riportare errori | | come l'irraggiungibilità di un host,la scadenza del | | TTL (Time to live) o "source quench" (letteralmente | | "spegnimento" dell'host sorgente) che significa che | | non c'è abbastanza memoria per proseguire l'invio | | del datagramma in questione. Non esiste un | | messaggio icmp per evitare cicli infiniti di un | | pacchetto in una rete. | | | | | | | | Schema dell'Header ICMP: | | | | | | 0 15-16 31 | | +-----------+-----------+-----------------------+ | | | Type | Code | Checksum | | | | (8 b) | (8 b) | (16 b) | | | +-----------+-----------+-----------------------+ | | | UNUSED | | | | (32 b) | | | +-----------------------------------------------+ | | | Internet Header + 64 bits di dati | | | | (32 b) | | | +-----------------------------------------------+ | | Questo è il formato standard dell'header icmp. | | Se però cambiano i valori dei campi "Type" e "Code" | | il campo "unused" (inutilizzato) viene utilizzato. | | Se "unused" rimane inutilizzato, settalo a 0. A | | seconda del tipo di messaggio icmp, alcuni campi del | | header Ip possono cambiare. | | | | | | | | ECHO REQUEST o ECHO REPLY | | ------------------------- | | | | L'Echo viene comunemente chiamato PING. Per | | generare la reply, lo stack inverte l'indirizzo Ip | | sorgente e destinazione nell'header Ip. Il campo | | "UNUSED" è diviso in campi da 8 bit ciascuno, chiamati | | Identifier e Sequence number, che descriverò qui sotto. | | | | | | TYPE (8 bits): | | 0 Per echo reply | | 8 Per echo request | | | | CODE (8 bits): | | 0 Campo inutilizzato per questo tipo | | di messaggi | | | | CHECKSUM (16 bits): | | Il checksum è calcolato come per gli altri | | header, ma il campo checksum deve essere 0 prima | | di averlo calcolato. Per rispettare il limite dei | | 32 bit, il kernel può "imbottire" il messaggio se | | la sua lunghezza totale è inaspettata, cioè minore | | dei 32 bit. | | | | Identifier (16 bits): | | Questo campo si comporta allo stesso modo | | dell'ID nell'headers ip, ma per gli echo e reply. | | Esso aiuta a capire quale echo reply appartiene a | | quale echo request (come per la frammentazione). | | | | Sequence Number (16 bits): | | Questo campo si comporta allo stesso modo | | dell'ID nell'headers ip, ma per gli echo e reply. | | Esso aiuta a capire quale echo reply appartiene a | | quale echo request (come per la frammentazione). | | | | | | Negli echo request possono essere inseriti anche i dati, | | questi poi saranno rispediti dall'host di destinazione | | nell'echo reply. | | | | | | | | | | DESTINATION UNREACHABLE | | ----------------------- | | | | Questo messaggio è utilizzato per indicare | | che un host o una rete è down, che un servizio non | | è in funzione, che lo stack non supporta il | | protocollo, che c'è bisogno della frammentazione ma | | "don't fragment" (DF) è settato, o che c'è stato un | | errore durante il routing del pacchetto. Il campo | | "UNUSED" rimane inutilizzato e dovrebbe essere | | settato a 0. | | | | | | TYPE (8 bits): | | 3 Destination Unreachable | | | | | | CODE (8 bits): | | 0 Rete irraggiungibile | | 1 Host irraggiungibile | | 2 Protocollo irraggiungibile | | 3 Porta irraggiungibile | | 4 Frammentazione necessaria ma DF settato. | | 5 Routing fallito | | | | | | | | CHECKSUM (16 bits): | | Il checksum è calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo.E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | SOURCE QUENCH | | ------------- | | | | Questo messaggio d'errore viene | | inviato quando un host o un gateway non ha | | abbastanza memoria per mettere in coda il | | pacchetto ricevuto per inoltrarlo. | | | | | | TYPE (8 bits): | | 4 Source Quench | | | | | | CODE (8 bits): | | 0 Inutilizzato | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo.E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | REDIRECT | | -------- | | | | Un messaggio redirect (di redirezione) è | | inviato quando esiste una strada più corta per | | arrivare alla destinazione. | | Esempio: | | | | Johnny invia un pacchetto alla rete R. La sua | | route table (tabella di routing) dice per | | default di inviarlo al Gateway #1, ma quando | | il Gateway #1 riceve il pacchetto esso trova | | una via più corta per arrivare alla | | destinazione. Esso quindi invia un REDIRECT | | all'ip sorgente specificando l'indirizzo Ip | | del nuovo gateway nel campo UNUSED. | | | | | | Vi è una eccezione quando l'"IP source routing" è | | abilitato,ma di questa opzione dell'ip non ho parlato | | in questo testo quindi mi fermo qui. | | | | | | TYPE (8 bits): | | 5 Redirect | | | | | | CODE (8 bits): | | 0 Redirige i datagrammi destinati ad una Rete | | 1 Redirige i datagrammi destinati ad un Host | | 2 Redirige i datagrammi destinati ad un TOS e | | ad una Rete | | 3 Redirige i datagrammi destinati ad un TOS e | | ad un Host | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | | | GATEWAY INTERNET ADDRESS (32 bits): | | Indirizzo Ip del gateway più vicino | | al quale inviare il pacchetto. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | TIME EXCEED | | ----------- | | | | Questo messaggio viene inviato quando il Time To | | Live (TTL)(tempo di vita) di un pacchetto scade o quando | | scade il tempo per riassemblare il pacchetto. | | | | | | TYPE (8 bits): | | 11 Time Exceed | | | | | | CODE (8 bits): | | 0 Time To Live Scaduto (TTL) | | 1 Tempo per il riassemblaggio dei frammenti | | scaduto | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | | | PARAMETER PROBLEM | | ----------------- | | | | Il messaggio "Parameter problem" | | (problemi di parametri) è inviato quando un | | datagramma ha valori errati nelle opzioni, | | TOS o un campo non valido. Il campo UNUSED | | viene riempito con un puntatore al campo | | errato. | | | | | | TYPE (8 bits): | | 12 Parameter problem | | | | | | CODE (8 bits): | | 0 Rende il campo POINTER significativo, | | cioè non viene ignorato | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | POINTER (8 bits): | | Viene preso in considerazione solo | | se CODE = 0. Esso punta all'area dove si | | trova l'errore. | | | | | | UNUSED (24 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | | | | | TIMESTAMP REQUEST e TIMESTAMP REPLY | | ----------------------------------- | | | | Tramite questi messaggi si comunica l'orario in | | secondi in cui il pacchetto è stato modificato l'ultima | | volta dalla mezzanotte UT (Universal Time). Quando il | | pacchetto viene inviato, l'orario viene inserito, e | | quando viene inviata la risposta a questo,viene inserito | | l'orario affianco a quello precedente. Tramite questo | | metodo possiamo calcolare quando sia distante da noi un | | host. | | | | | | TYPE (8 bits): | | 13 Timestamp Request | | 14 Timestamp Reply | | | | | | CODE (8 bits): | | 0 Rende l'ID e il Seq Num significativi | | (non vengono ignorati) | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | IDENTIFIER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | SEQUENCE NUMBER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | | | NETMASK REQUEST e NETMASK REPLY | | ------------------------------- | | | | Questo messaggio icmp restituisce la | | maschera di rete dell'host che invia il messaggio. | | Per generare la reply, gli indirizzi Ip sorgente e | | destinazione vengono invertiti, viene inserito la | | maschera di rete nel campo, viene ricalcolato il | | checksum e viene spedito al mittente. Se il | | mittente non conosce il proprio Ip, egli inserisce | | 0 nel campo del source ip adress, e la risposta al | | pacchetto verrà inviata all'indirizzo Ip di | | broadcast. | | | | | | | | TYPE (8 bits): | | 17 Netmask Request | | 18 Netmaks Reply | | | | | | CODE (8 bits): | | 0 Rende l'ID e il Seq Num significativi | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | IDENTIFIER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | SEQUENCE NUMBER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | | | | | | | | | ---[ Esempi | | | | | | | | | | /****************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header ICMP (PING) */ | | /* */ | | /****************************************************************/ | | | | | | | | void icmp_build(){ | | | | struct icmphdr *icmp; | | | | icmp = (struct icmphdr *) malloc(sizeof(struct icmphdr)); | | | | icmp->type = ICMP_ECHO; /*** ECHO REQUEST */ | | icmp->code = 0; /*** Campi Id e Sequence significativi */ | | icmp->un.echo.id = 0; /*** Per identificare la risposta al ping */| | icmp->un.echo.sequence = 0; /*** Per identificare la risposta al ping */ | | icmp->checksum = 0; /*** Il campo checksum deve essere 0 | | prima del calcolo */ | | | | icmp->checksum =in_cksum((unsigned short *)icmp,sizeof(struct icmphdr)); | | /*** Checksum */ | | | | } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ CAPITOLO 5 ] | | (IMPLEMENTAZIONE) | | | | | | ---[ Teoria | | | | Dopo questa teoria sui vari header | | dei protocolli, dobbiamo ora abbandonare la | | teoria per passare alla implementazione vera | | e propria. Fondamentalmente ciò che descrivo | | in questo testo è come creare un socket | | utilizzando il livello raw, come riempire | | la struttura del socket e come comunicare ad | | un livello così basso. | | | | Per prima cosa osserveremo man mano | | un codice sorgente e per ogni linea | | spiegherò il suo significato. Andiamo: | | | | | | int sock, optval; /*** Descrittore del socket ***/ | | struct sockaddr_in peer; /*** Struttura usata da sendto() ***/ | | | | | | Se non capisci qualcosa, credo sia meglio | | che tu prenda un libro sulla programmazione | | dei socket su sistemi unix. | | | | if ((sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1){ | | perror("Errore nella creazione del socket"); | | return -1; | | } | | | | | | Queste linee creano un socket utilizzando | | il TCP come protocollo di trasporto. Il | | socket è SOCK_RAW per permettere l'accesso | | raw. E' utilizzato AF_INET poichè ci | | troviamo su internet. Da ora, se socket() | | restituisce un errore, perror() | | visualizzerà il contenuto di errno e ciò | | che ha restituito la funzione. | | | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | | | | | Questa funzione dice al socket sock che | | lavoriamo al livello IPPROTO_IP e che noi | | includeremo l'header ip (IP_HDRINCL) nei | | pacchetti inviati. optval e sizeof(int) | | non sono importanti per questa opzione, | | quindi non parlerò di loro. | | | | | | peer.sin_family = AF_INET; | | peer.sin_port = htons(23); | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | | | | | Qui riempiamo la struttura sockaddr_in | | (peer) utilizzata da sendto().Diciamo che è | | un protocollo di famiglia Internet(AF_INET). | | La porta di destinazione è la 23. | | Utilizziamo htons() per la giusta sequenza | | dei byte, come detto all'inizio. Nella | | linea successiva settiamo l'indirizzo di | | destinazione utilizzando inet_addr() per | | convertire l'indirizzo in formato binario. | | | | A questo punto dovremmo costruire il nostro | | pacchetto. Prenderò per scontato le cose | | di cui ho parlato nella teoria. | | | | | | sendto(sock, packet, strlen(packet),0, | | (struct sockaddr *)&peer,sizeof(struct sockaddr)); | | | | | | | | Inviamo il pacchetto packet sul socket sock | | per la lunghezza strlen(packet). Nel parametro | | successivo settiamo 0, poichè non indichiamo | | alcun flag. Vi sono 4 flag: | | | | MSG_OOB Questo invia un pacchetto | | Out Of Bound, aumentando la sua | | priorità. | | | | MSG_DONTROUTE Non osserva la tabella di | | routing e invia direttamente | | all'interfaccia. | | | | MSG_DONTWAIT Normalmente sendto() può | | trattenere un pacchetto, ma con | | questo flag, non lo farà e | | restituirà EAGAIN. | | | | MSG_NONSIGNAL Chiede di non inviare il | | segnale SIGPIPE quando uno stream | | orientato alla connessione | | fallisce cioè genera un errore o | | si disconnette. | | | | | | Poi, con ((struct sockaddr *)&peer), chiediamo | | al peer di specificare la famiglia di | | protocolli, e la porta e l'indirizzo di | | destinazione poichè sendto si aspetta di | | avere un puntatore alla struttura sockaddr. | | Infine specifichiamo la lunghezza della | | struttura sockaddr tramite | | (sizeof(struct sockaddr)) e il datagramma è | | inviato!! | | | | Per essere sicuro di aver capito, scrivi | | questo esempio e prova a ricevere il | | pacchetto e stamparne il risultato. Ho | | creato dei programmini nella seguente | | sezione in modo che tu possa verificare di | | aver capito bene. | | | | Suggerimento: man recv | | | | buona fortuna | | | | | | -----[ Conclusioni ]--- | | | | | | | | | | Ho fatto il meglio che potevo per creare | | un testo completo e buono sulla programmazione delle | | raw socket. Spero che il testo ti sia piaciuto e sono | | sicuro che ti abbia aiutato nel capire come codare | | con le raw socket. Questo documento mi ha aiutato | | a capire delle cose di cui non ero sicuro e ad | | imparare delle cose che non avevo mai sentito prima. | | Infine, vorrei approfittare di questo momento per | | dire ufficialmente che in breve tempo rilascerò un | | portscanner simile a nmap. Sto provando a migliorarne | | la velocità e lo stile di codifica per renderlo più | | leggibile a persone "ordinarie" come me. Questo | | progetto è chiamato ESCAN ed include molte funzioni | | come: connect scan, stealth, half open, decoys, | | logging. Una versione beta dovrebbe essere rilasciata | | il prima possibile. Per seguire lo sviluppo: | | http://www.exile2k.org | | | | | | | | | | [ Appendice A ] | | (Strutture e Funzioni) | | | | | | | | | | | | | | ---[ STRUTTURA HEADER IP | | | | | | | | struct iphdr { | | | | #if __BYTE_ORDER == __LITTLE_ENDIAN | | unsigned int ihl:4; | | unsigned int version:4; | | #elif __BYTE_ORDER == __BIG_ENDIAN | | unsigned int version:4; | | unsigned int ihl:4; | | #else | | # error "Please fix <bits/endian.h>" | | #endif | | u_int8_t tos; | | u_int16_t tot_len; | | u_int16_t id; | | u_int16_t frag_off; | | u_int8_t ttl; | | u_int8_t protocol; | | u_int16_t check; | | u_int32_t saddr; | | u_int32_t daddr; | | /*The options start here. */ | | }; | | | | | | | | | | | | | | ---[ STRUTTURA PSEUDO HEADER | | | | | | | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER TCP | | | | | | | | | | struct tcphdr { | | __u16 source; | | __u16 dest; | | __u32 seq; | | __u32 ack_seq; | | #if defined(__LITTLE_ENDIAN_BITFIELD) | | __u16 res1:4, | | doff:4, | | fin:1, | | syn:1, | | rst:1, | | psh:1, | | ack:1, | | urg:1, | | res2:2; | | #elif defined(__BIG_ENDIAN_BITFIELD) | | __u16 doff:4, | | res1:4, | | res2:2, | | urg:1, | | ack:1, | | psh:1, | | rst:1, | | syn:1, | | fin:1; | | #else | | #error "Adjust your <asm/byteorder.h> defines" | | #endif | | __u16 window; | | __u16 check; | | __u16 urg_ptr; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER UDP | | | | | | | | struct udphdr { | | __u16 source; | | __u16 dest; | | __u16 len; | | __u16 check; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER ICMP | | | | | | | | | | struct icmphdr { | | __u8 type; | | __u8 code; | | __u16 checksum; | | union { | | struct { | | __u16 id; | | __u16 sequence; | | } echo; | | __u32 gateway; | | struct { | | __u16 __unused; | | __u16 mtu; | | } frag; | | } un; | | }; | | | | | | | | | | | | ---[ FUNZIONE PER IL CALCOLO DEL CHECKSUM | | | | | | | | | | /* | | * in_cksum -- | | * Checksum routine for Internet Protocol | | * family headers (C Version) | | */ | | unsigned short in_cksum(unsigned short *addr, int len) | | { | | register int sum = 0; | | u_short answer = 0; | | register u_short *w = addr; | | register int nleft = len; | | | | /* | | * Our algorithm is simple, using a 32 bit accumulator (sum), we add | | * sequential 16 bit words to it, and at the end, fold back all the | | * carry bits from the top 16 bits into the lower 16 bits. | | */ | | while (nleft > 1) | | { | | sum += *w++; | | nleft -= 2; | | } | | | | /* mop up an odd byte, if necessary */ | | if (nleft == 1) | | { | | *(u_char *) (&answer) = *(u_char *) w; | | sum += answer; | | } | | /* add back carry outs from top 16 bits to low 16 bits */ | | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | | sum += (sum >> 16); /* add carry */ | | answer = ~sum; /* truncate to 16 bits */ | | return (answer); | | } | | | | | | | | | | | | | | | | ----[ Codici sorgente | | | | | | /********************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un pacchetto ICMP (PING) */ | | /* includendo l'header IP */ | | /* */ | | /* */ | | /* */ | | /* */ | | /********************************************************************/ | | | | | | #include <stdio.h> | | | | #include <linux/ip.h> | | #include <linux/icmp.h> | | #include <netinet/in.h> | | #include <sys/types.h> | | #include <sys/socket.h> | | | | | | | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | | | int main(){ | | | | int sock, optval; | | char *packet, *buffer; | | | | struct icmphdr *icmp; | | | | struct sockaddr_in peer; | | struct iphdr *ip; | | | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | icmp = (struct icmphdr *) malloc(sizeof(struct icmphdr)); | | packet= (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr)); | | buffer= (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr)); | | | | | | ip = (struct iphdr *) packet; | | icmp = (struct icmphdr *) (packet + sizeof(struct iphdr)); | | | | | | ip->ihl = 5; | | ip->version = 4; | | ip->tos = 0; | | ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); | | ip->id = htons(getuid()); | | ip->ttl = 255; | | ip->protocol = IPPROTO_ICMP; | | ip->saddr = inet_addr("127.0.0.1"); | | ip->daddr = inet_addr("127.0.0.1"); | | | | | | sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | icmp->type = ICMP_ECHO; | | icmp->code = 0; | | icmp->un.echo.id = 0; | | icmp->un.echo.sequence = 0; | | icmp->checksum = 0; | | | | icmp->checksum = in_cksum((unsigned short *)icmp,sizeof | | (struct icmphdr)); | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | | | | | | | peer.sin_family = AF_INET; | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | | | sendto(sock,packet,ip->tot_len,0,(struct sockaddr *)&peer,sizeof | | (struct sockaddr)); | | | | recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct icmphdr),0); | | printf("Ricevuto l'ECHO REPLY\n"); | | | | close(sock); | | return 0; | | } | | | | | | | | | | | | | | | | | | /********************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione csotruisce un pacchetto UDP */ | | /* includendo l'header IP ed inviandlo al server echo locale */ | | /* */ | | /* Per far funzionare il programma abilita il server echo: */ | | /* */ | | /* - pico /etc/inetd.conf */ | | /* - Elimina i simboli del commento dalla riga */ | | /* dell'echo server (udp one) */ | | /* - killall -HUP inetd */ | | /* */ | | /* */ | | /* */ | | /* */ | | /********************************************************************/ | | | | | | #include <stdio.h> | | | | #include <linux/ip.h> | | #include <linux/udp.h> | | #include <netinet/in.h> | | #include <sys/types.h> | | #include <sys/socket.h> | | | | | | | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | | | | | int main(){ | | | | int sock, optval; | | char *packet, *buffer; | | | | struct udphdr *udp; | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }pseudo; | | | | struct sockaddr_in peer; | | struct iphdr *ip; | | | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | udp = (struct udphdr *) malloc(sizeof(struct udphdr)); | | packet = (char *) malloc(sizeof(struct iphdr) + | | sizeof(struct udphdr) + 12); | | buffer = (char *) malloc(sizeof(struct iphdr) + | | sizeof(struct udphdr) + 12); | | | | | | ip = (struct iphdr *) packet; | | udp = (struct udphdr *) (packet + sizeof(struct iphdr)); | | | | | | ip->ihl = 5; | | ip->version = 4; | | ip->tos = 0; | | ip->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) +12; | | ip->id = htons(getuid()); | | ip->ttl = 255; | | ip->protocol = IPPROTO_UDP; | | ip->saddr = inet_addr("127.0.0.1"); | | ip->daddr = inet_addr("127.0.0.1"); | | | | | | sock = socket(AF_INET,SOCK_RAW,IPPROTO_UDP); | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | pseudo.saddr = inet_addr("127.0.0.1"); | | pseudo.daddr = inet_addr("127.0.0.1"); | | pseudo.useless = htons(0); | | pseudo.protocol = IPPROTO_UDP; | | pseudo.length = sizeof(struct udphdr) + 12; | | | | | | udp->source = htons(5000); | | udp->dest = htons(7); | | udp->len = htons(sizeof(struct udphdr) + 12); | | udp->check = in_cksum((unsigned short *)&pseudo,sizeof(struct udphdr) | | + sizeof(struct pseudohdr) + 12); | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | | | | | strcpy((packet+sizeof(struct iphdr) + sizeof(struct udphdr)), | | "Hello World"); | | | | peer.sin_family = AF_INET; | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | peer.sin_port = htons(7); | | | | sendto(sock,packet,ip->tot_len,0,(struct sockaddr *)&peer,sizeof | | (struct sockaddr)); | | | | recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct udphdr)+13,0); | | | | buffer += (sizeof(struct iphdr)+sizeof(struct udphdr)); | | printf("Reply from Echo server:\t%s\n",buffer); | | | | close(sock); | | return 0; | | } | | | | [ Riferimenti ] | | | | | | | | Tcp/Ip Illustrated Volume 1 (The Protocol) | | By W. Richard Stevens (Addison Wesley) | | | | Tcp/Ip Illustrated Volume 2 (The implementation) | | By Gary R. Wright and W. Richard Stevens (Addition Wesley) | | | | Dai un'occhiata qui: | | | | http://www.exile2k.org Exile Team home page | | http://www.hexedit.com HNS home page | | http://www.eEyes.com eEyes home page | | | | | | | | [ Ringraziamenti ] | | | | | | | | Special thanx to: | | My Exile team bro's: Mayhem(Tutu rose emulator), | | Rix(Assembly wh0re), | | Kraken(Saleter dhypee), | | Ehoba(Pas toi!!!), | | Liks(Erm...) | | | | or Europeen wh0res kinda synonyms =] | | ---> keep it kool guys! | | | | #rhino9 peeps: Colonwq(Gotta learn you howto drink), | | Hexedit(Lucky to be yourself), | | Binf(Mon mentor de hacking y0), | | Klog(Bleh j00), | | zorkeres(Still sickshit addict?), | | RcLocal(The french skill0rz), | | and others | | | | People who supported me even if i was newbie: Utopiste, | | Wyzeman... | | | | ~ My parents who made it possible during 1982's night... ~ | | | | God bless people i forget... | | | | | | | | | | | | Nitr0gen Exile Team 2000 Rock on! | | nitr0gen@hackersnews.com | | | | | | Tradotto da XpTerminator: | | | | spero proprio di aver tradotto bene... | | per qualunque genere di errore segnalate a: | | | | xp_terminator@katamail.com | | http://xpterminator.cjb.net | | | | Ciao a tutti! | | | | | +--------------------------------------------------------------------------+