TCP:IP Hacks

Embed Size (px)

DESCRIPTION

TCP:IP Hacks

Citation preview

===============================================================================-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=---------------------[ previous ]---[ index ]---[ next ]---------------------

--------------------[ TCP/iP HACKS F0R PHUN AND PR0FiT ]---------------------------------------------[ da: TCP/iP T00LS UNLiMiTED ]----------------------------------------------------------[ FuSyS ]-----------------------------------

NO(C)1999 FuSyS#############################################################################DISCLAIMERSe qualcuno si sta ormai chiedendo che diavolo siano questi benedetti TCP/IPTools Unlimited da cui traggo articoli e codici... beh, NON si tratta diun libro ordinabile da Amazon :) e no, non e' neanche un phile di testo.Non e' un manuale tecnico ne' materiale trafugato da una telco. Ma seancora non ci aveste pensato, bastera' che raccogliate tutti i numeri diBFi e potrete avere il grosso di questi miei scritti tutto per voi :)In arrivo col numero 7 di BFi un pratico raccoglitore cartonato!#############################################################################

URL del numero: http://www.iinet.net.au/~bofh/index.html Se non avete mai letto gli aneddoti di Simon, BOfH per eccellenza, alloranon avete il diritto di continuare a leggere BFi :PAh, per chi non lo sapesse, BOfH sta per Bastard Operator fROM Hell :)))

Ok bando alla perdita di tempo.Quello che avete tra le mani (no, non PgDn o ^[[B) e' un testo su alcuniaspetti del set di protocolli TCP/IP che possano esserci utili in unarete. Per rete questa volta non intendo necessariamente InterNet, quantoanche una piccola LAN, magari quella della scuola, dell'ufficio, di cameravostra o della vostra CON(vention) preferita.

Per hacks intendo piccoli usi e variazioni sul tema in maniera abile egiocosa piu' che diretti ad un preciso fine. Se vi state chiedendo se sipossa usare con questa accezione, beh, si puo'. Lo dice il jargon :)

Requisiti: conoscenza di base di TCP/IP ['di base' non vuol dire 'nulla']

T C P / I P

In alcuni dei miei articoli ho gia' presentato alcune caratteristiche diquesto set di protocolli. Ho mostrato gli header ed alcune librerie usateper la programmazione a basso livello. Si', perche' non possiamo o dobbiamoassolutamente accontentarci di usare le normali chiamate delle API BSDsocket per manipolare le connessioni e le macchine intorno a noi. Ne'possiamo fidarci del kernel perche' agisca come vorremmo noi :) ....Come abbiamo visto nella prima parte del progetto 0N0S3NDAi abbiamo lapossibilita' di creare i nostri pacchetti IP ed inserirli nel normaleflusso della comunicazione gestito dal kernel. Cosi' possiamo forgiarepacchetti con indirizzi spoofati, possiamo manipolare connessioni edintercettare dati.

Questo e' alla base anche di questo articolo. Per prima cosa quindi vimostro come creare un semplice pacchetto IP. No, non un vero e proprioprogramma quanto una specie di HOWTO.

Abbiamo per prima cosa bisogno di un po' di memoria, di un buffer. Quelloche potete facilmente vedere spulciando nei sorgenti del kernel di linux odi un BSD, e' come il sistema gestisca le comunicazioni usando dei bufferche vengono manipolati man mano che si passa da uno strato all'altro delset di protocolli [in un prossimo articolo vedremo tutto il passaggiodalla scheda di rete all'applicazione e viceversa nel nuovo kernel dilinux, il 2.2]. Questi buffer, chiamati sk_buff sotto linux e mbuf sottoBSD4.4, servono per contenere gli header ed i dati dei pacchetti IP (ma non solo) che vengono poi trasmessi dalle varie interfacce di rete delsistema. Si', anche via modem avete un'interfaccia di rete. E' proprioquella che attraverso SLIP/PPP ed il modem comunica con il gateway delvostro ISP.

Quindi, non usando il kernel per i nostri pacchetti non possiamo avere unbuffer di questo tipo. Ci accontenteremo :) di un semplice array dichar. Per l'uso che ne faremo possono bastare array di non piu' di 1500,2500 byte. Ovviamente sta poi a voi ed all'uso che ne farete, ed allaimplementazione dei vostri tool, la specifica delle dimensioni deisuddetti array. Infatti il kernel sara' comunque in grado di frammentareper noi tali pacchetti a seconda del MTU della interfaccia di rete.

char buffer[1500];

Ho gia' parlato delle strutture dati ip, udp, tcp e icmp... basta che vispulciate ben bene la dir /usr/include/netinet/ alla ricerca di quel chefa per voi. In questo caso, creando un semplice pacchetto IP useremo solo :

struct iphdr *ip;

Perche' un puntatore a questa struttura? [sorry, ma non saro' io qui adirvi cosa sia un puntatore]. Semplice. Perche' useremo il puntatore comefoglio di carta velina da 'apporre' al nostro buffer per riempirlo come sideve.

Dobbiamo pero' anche comunicare al kernel che abbiamo intenzione di crearenoi i nostri pacchetti, quindi la chiamata di socket(2) usera' come typeSOCK_RAW e come protocol IPPROTO_RAW. Dovremo anche comunicare la nostraintenzione di manipolare direttamente l'header di IP. Quindi useremosetsockopt(2), utilizzando IPPROTO_IP come level e IP_HDRINCL comeoptname. Mi raccomando di controllare sempre le pagine man dei comandi efunzioni che nomino.

A questo punto posso tranquillamente apporre il mio puntatore al mio buffer:

ip = (struct iphdr*) buffer;

Cosi' facendo avro' la possibilita' di manipolare il buffer come farebbe(non proprio :) il kernel all'atto della creazione di un pacchetto:

ip->ihl = 5;ip->version = 4;/* ip->tos */ip->tot_len = htons(sizeof(ip));ip->id = 0;ip->frag_off = 0;ip->ttl = htons(255);ip->protocol = IPPROTO_IP;/* ip->check */ip->saddr = inet_addr("1.1.1.1");ip->daddr = inet_addr("2.2.2.2");

Alcuni parametri li ho saltati in quanto il kernel provvedera' lui stesso,all'atto della trasmissione, a completare l'header di IP. A questo puntoposso inviare il tutto mediante una semplice chiamata sendto(2) dopo averovviamente riempito anche una struttura di tipo sockaddr_in con il tipo diprotocollo (AF_INET), l'indirizzo del destinatario, ed il numero di portanel caso di TCP o UDP (0 negli altri).

Questo metodo e' quello utilizzato spessissimo, se non quasi sempre, inmoltissimi codici e tools di ogni genere in cui ci sia bisogno dimanipolare a basso livello TCP/IP. Ovviamente creare un pacchetto eportare avanti connessioni, attacchi o difese non e' la stessa cosa. Masenza sapere come forgiare pacchetti, sara' dura fare il resto :)Ora che questa e' fatta, passiamo ai TCP/IP hacks di questo articolo.

D I S T R U Z I O N E C O N N E S S I O N I T C P / I P

Nello scorso numero di BFi vi ho mostrato come avviene l'inizio di unaconnessione TCP, ovvero mediante il 3-way handshake. In questo articoloinvece vi mostrero' come le connessioni vengono chiuse.

Vi sono essenzialmente due modi che si rifanno a due delle flag TCP: FIN eRST.

Il primo metodo e' quello speculare del 3-way, senonche' servono 4passaggi e non solo 3. Questo metodo e' quello del cosiddetto HALF-CLOSE.Se infatti consideriamo la connessione TCP come full-duplex, possiamofacilmente capire che entrambe le parti in causa debbano chiudere la lorotrasmissione. Per far questo si usa la flag FIN, di norma inviata quandol'applicazione ha chiamato la chiusura del socket. La ricezione di un FINnon vuol quindi dire che la connessione sia ultimata, quanto che e' statachiusa dalla parte che l'ha trasmessa. Per questo prende il nome dihalf-close.

In pratica una parte invia un pacchetto TCP con la flag FIN, con o senzatrasmissione di ultimi dati mediante PSH. Il peer, risponde con un ack delseq+1 ed invia a sua volta un pacchetto con i suoi ultimi dati (o no,appena la trasmissione e' finita) e la flag FIN, che verra' riconosciutacon un ack dalla prima parte che ha avviato la chiusura. Al solito undiagramma aiutera', spero, la comprensione.

-------------------------------------------------------- | | | ----------- FIN -----------> | | flags&(IFF_PROMISC)) { if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) skb->pkt_type=PACKET_OTHERHOST; }

qui se la flag IFF_PROMISC e' stata settata per l'interfaccia di rete, allorail tipo di pacchetto viene considerato non indirizzato alla nostrainterfaccia, dopo aver ovviamente controllato che l'indirizzo non corrispondae non sia BROADCAST (190.299).

/usr/src/linux/net/ipv4/[email protected]

if(skb->pkt_type == PACKET_OTHERHOST) { kfree_skb(skb, FREE_READ); return 0; }

qui notiamo per la prima volta nel kernel 2.0.36 che nel caso il tipo dipacchetto, specificato nel buffer skb sia PACKET_OTHERHOST, allora ilbuffer viene scartato e non avviene processo ARP. Quindi la destinazionehardware dei pacchetti ARP dev'essere BROADCAST o MULTICAST, oppure devecorrispondere al valore locale. Questo annulla ogni risultato di neped.cqualora venga effettuato lo scan su macchine con 2.0.36 ... e non permetteneanche di modificare l'indirizzo in BROADCAST in quanto questo negherebbela deduzione sulla modalita' promiscua.

Non c'e' quindi modo di sapere se ci siano sniffer su macchinecon 2.0.36 ???? SI' CHE C'E' :)))) ed ora lo vedremo.

Ho controllato dentro ai sorgenti del kernel di linux ed ho visto che lostack relativo a ICMP permette un giochino simile a quello fatto con ARP.Ovvero possiamo creare delle richieste di tipo ECHO indirizzandole adethernet inesistenti. Ebbene, le macchine con kernel 2.0.36, ed inferioriovviamente, risponderanno allegramente alla query con un ECHO_REPLY se laloro interfaccia e' in modalita' promiscua.

Vediamo ora il codice.

---------- snip ----------/************************************************************************* proscan.c PROMISC Ethernet Scanner** **Questo tool permette la scansione di un LAN**alla ricerca di interfacce di rete in modalita' **promiscua. L'effetto viene ottenuto mediante* *utilizzo di query 'anomale'.* *Per la spiegazione vedere l'articolo " TCP/IP **Hacks For Phun And Profit" su BFi5.** BFi e' disponibile al seguente URL:** http://softpj98.bbk.org/bfi/** ** OS: Linux (SOCK_PACKET) ** Credits:Apostols, comp.security.unix, vari sniffer :) * * ** NO(C)1998 FuSyS TCP/IP Tools Unlimited *************************************************************************/

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include

#define MAX_LEN1500#define IF_LEN14#define IP_ALEN4#define IP_HLEN 20#define ICMP_HLEN 8

struct arp_hack {unsigned char h_dest[ETH_ALEN];unsigned char h_source[ETH_ALEN];unsigned short h_proto;unsigned short ar_hrd;unsigned short ar_pro;unsigned char ar_hln;unsigned char ar_pln;unsigned short ar_op;unsigned char ar_sha[ETH_ALEN];unsigned char ar_sip[IP_ALEN];unsigned char ar_tha[ETH_ALEN];unsigned char ar_tip[IP_ALEN];};

struct pinghack { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; unsigned short h_proto; unsigned char ihl_ver; unsigned char tos; unsigned short tot_len; unsigned short id; unsigned short frag_off; unsigned char ttl; unsigned char protocol; unsigned short check; unsigned long saddr; unsigned long daddr; unsigned char type; unsigned char code; unsigned short checksum; unsigned short icmp_id; unsigned short icmp_seq;};

unsigned char mac[ETH_ALEN];unsigned long dip, sip, netmask, broadcast, dmp, saddr;char packet[MAX_LEN], *ptr;

void uso(void) { fprintf(stderr,"Uso: proscan -[a,p] \n"); exit (0);}

char *ntoa(unsigned long ip) { static char buff[18]; char *p; p = (char *) &ip; sprintf(buff, "%d.%d.%d.%d", (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); return(buff);}

char *dumpHW (unsigned char *hw_s) {static char buffer[ETH_ALEN];sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", hw_s[0], hw_s[1], hw_s[2], hw_s[3], hw_s[4], hw_s[5]);return buffer;}

unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { unsigned int sum;

__asm__ __volatile__(" movl (%1), %0 subl $4, %2 jbe 2f addl 4(%1), %0 adcl 8(%1), %0 adcl 12(%1), %01: adcl 16(%1), %0 lea 4(%1), %1 decl %2 jne 1b adcl $0, %0 movl %0, %2 shrl $16, %0 addw %w2, %w0 adcl $0, %0 notl %02: " : "=r" (sum), "=r" (iph), "=r" (ihl) : "1" (iph), "2" (ihl)); return(sum);}

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

struct arp_hack *hack_p;struct pinghack *ping;struct ifreq ifr;struct sockaddr sa;int opt, sockfd, fd_flags, len, sa_len, pid, sent, optA=0, optP=0;

if (geteuid() || getuid()) { fprintf(stderr, "Per utilizzare proscan devi essere Root\n",argv[0]); exit(0); }

if (argc < 3) uso();

while ((opt = getopt(argc, argv, "ap")) != EOF) { switch(opt) { case 'a': optA=1; break; case 'p': optP =1; break; default: exit(1); break; } }

if(optA && optP) {fprintf(stderr, "\nNon puoi usare -a e -p insieme !!!\n");exit(1);}

printf("\n\033[1;32m---] P R O m i s c S C A N n e r [---\033[0m\n");printf("\033[1;34mno(C)1999 FuSyS - TCP/IP Tools Unlimited\033[0m\n");

if(optA) if((sockfd=socket(AF_INET, SOCK_PACKET, htons(ETH_P_ARP))) h_proto = htons(ETH_P_ARP);hack_p->ar_hrd = htons(ARPHRD_ETHER);hack_p->ar_pro = htons(ETH_P_IP);hack_p->ar_hln = 6;hack_p->ar_pln = 4;hack_p->ar_op = htons(ARPOP_REQUEST);memcpy (hack_p->ar_sha, mac, ETH_ALEN);memcpy (hack_p->ar_sip, &sip, IP_ALEN);memcpy (hack_p->ar_tha, "\0\0\0\0\0\0", ETH_ALEN);dmp=htonl(dip);memcpy (hack_p->ar_tip, &dmp, IP_ALEN);

strcpy(sa.sa_data, argv[2]); sa.sa_family = AF_UNIX;

if( sendto (sockfd, packet, sizeof (struct arp_hack), 0, &sa, sizeof(sa)) ar_sip, IP_ALEN);

if ( ntohs(hack_p->ar_op) == ARPOP_REPLY && dmp == sip && (dip-ntohl(saddr) >= 0 ) && (dip-ntohl(saddr) ar_sha)); } }

if(optP) for(dip=(ntohl(sip)&ntohl(netmask))+1;diph_dest, "\0\1\0\1\0\1", ETH_ALEN); memcpy(ping->h_source, mac, ETH_ALEN); ping->h_proto = htons(ETH_P_IP); ping->ihl_ver = 0x45; ping->tos = 0x00; ping->tot_len = htons(IP_HLEN+ICMP_HLEN); ping->id = 0x0000; ping->frag_off = 0x0000; ping->ttl = 0xFF; ping->protocol = IPPROTO_ICMP; ptr += 26; *((u_long *)ptr) = sip; ptr += 4; *((u_long *)ptr) = htonl(dip); ping->check = 0; ping->check = ip_fast_csum((unsigned char *) ping+ETH_HLEN, 20); ptr +=4; *((u_char *)ptr) = 8; ptr +=1; *((u_char *)ptr) = 0; ptr +=3; *((u_short *)ptr) = pid; ptr +=2; *((u_short *)ptr) = 0xF001; ping->checksum = 0; ping->checksum = ip_fast_csum((unsigned char *) ping+(ETH_HLEN+IP_HLEN), 8);

if((sent=sendto(sockfd, &packet, ETH_HLEN+IP_HLEN+ICMP_HLEN, 0, &sa, sa_len)) < 0 ) { fprintf(stderr, "Errore sendto\n"); return(-1); } usleep(50); memset(&packet, 0, MAX_LEN); ptr = packet;

len = recvfrom (sockfd, packet, ETH_HLEN+IP_HLEN+ICMP_HLEN, 0, &sa, &sa_len); if (len = 0) && (dip - ntohl(*((u_long*)ptr))