No, non
preoccupatevi non faccio e non faro mai uso di stupefacenti. Questo non
e' altro che un articolo riguardante lo sniff che e' l'arte di intercettamento
di una comunicazione via internet. Esistono in giro sulla rete vari software
per poter sniffare; il piu' famoso nel mondo UNIX e' il TCPDUMP (e gia
il nome dice tutto). Esiste anche software per DOS ed NT che pero' ha il
problema dell'accesso diretto da parte di un task alla scheda di rete.
Tutto il traffico che passa su un cavo in cui noi abbiamo accesso puo'
essere sniffato, l'utilizzo migliore dello sniff avviene con la rete ethernet.
Ethernet non e' altro che un protocollo che lavora spedendo i pacchetti
con le informazioni a tutti i computer collegati a tale rete, l'intestazione
del pacchetto contiene il proprio indirizzo e l'indirizzo di destinazione.
Gli sniffer
funzionano in maniera molto semplice non fanno altro che dire alla scheda
di rete di raccogliere tutti i pacchetti che passano sul cavo di rete invece
che solo quelli che sono destinati all'indirizzo della scheda, questo avviene
settando quest'ultima in modalita' PROMISCUE MODE in modo da potergli dire
di ricevere tutti i pacchetti che transitano sulla sua scheda. Questo succede
perche' la scheda quando riceve i pacchetti ethernet prende solo quelli
destinati al suo MAC address. Se la macchina da noi utilizzata e' collegata
con un cavo coassiale abbiamo la possibilita' di utilizzare lo sniff in
modo piu' approfondito che utilizzando solo il doppino telefonico dato
che su quest'ultimo passano solo i pacchetti destinati alla mia macchina.
Come gia' molti di voi sapranno che il cavo coassiale e' gia' di per se
un mezzo BROADCAST quindi abbiamo la possibilita' di sentire tutto quello
che gli altri dicono sul filo elettrico.
Se avete
anche la possibilita' di avere accesso al cavo che collega i vari router
al MIX (che e' il nodo di interscambio di traffico tra i vari provider)
allora occorre delimitare lo spezzone della rete, dobbiamo, cioe', selezionare
quello che ci interessa indicando gli indirizzi di arrivo e di partenza
in modo da non sovraccaricare il SO. Chiaramente uno sniffer va' su qualsiasi
macchina della nostra rete:
sulla macchina
remota, sul server locale o su una terza macchina, il tutto dipende dal
tipo di rete che collega i nodi presi in questione.
Un esempio
pratico: io mi trovo in una universita' e quindi ho molte piu' possibilita'
di sniffare del traffico che passa sui miei cavi rispetto a quello che
passa in Finlandia.
Ci sono
vari prodotti di sniff in giro ma per ora ve ne lascio uno da compilare
:
/* [JOIN THE POSSE!] */
/* Esniff.c */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/stropts.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/nit_if.h>
#include <net/nit_buf.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <arpa/inet.h>
#define ERR stderr
char *malloc();
char *device,
*ProgName,
*LogName;
FILE *LOG;
int debug=0;
#define NIT_DEV
"/dev/nit"
#define CHUNKSIZE 4096
/* device buffer size */
int if_fd = -1;
int Packet[CHUNKSIZE+32];
void Pexit(err,msg)
int err; char *msg;
{ perror(msg);
exit(err); }
void Zexit(err,msg)
int err; char *msg;
{ fprintf(ERR,msg);
exit(err); }
#define IP
((struct ip *)Packet)
#define IP_OFFSET (0x1FFF)
#define SZETH
(sizeof(struct ether_header))
#define IPLEN
(ntohs(ip->ip_len))
#define IPHLEN
(ip->ip_hl)
#define TCPOFF
(tcph->th_off)
#define IPS
(ip->ip_src)
#define IPD
(ip->ip_dst)
#define TCPS
(tcph->th_sport)
#define TCPD
(tcph->th_dport)
#define IPeq(s,t) ((s).s_addr
== (t).s_addr)
#define TCPFL(FLAGS) (tcph->th_flags & (FLAGS))
#define MAXBUFLEN (128)
time_t LastTIME = 0;
struct CREC {
struct CREC *Next,
*Last;
time_t
Time;
/* start time */
struct in_addr
SRCip,
DSTip;
u_int
SRCport, /*
src/dst ports */
DSTport;
u_char
Data[MAXBUFLEN+2]; /* important stuff :-) */
u_int
Length;
/* current data length */
u_int
PKcnt;
/* # pkts */
u_long
LASTseq;
};
struct CREC *CLroot = NULL;
char *Symaddr(ip)
register struct in_addr ip;
{ register struct hostent *he =
gethostbyaddr((char
*)&ip.s_addr, sizeof(struct in_addr),AF_INET);
return( (he)?(he->h_name):(inet_ntoa(ip))
);
}
char *TCPflags(flgs)
register u_char flgs;
{ static char iobuf[8];
#define SFL(P,THF,C) iobuf[P]=((flgs &
THF)?C:'-')
SFL(0,TH_FIN, 'F');
SFL(1,TH_SYN, 'S');
SFL(2,TH_RST, 'R');
SFL(3,TH_PUSH,'P');
SFL(4,TH_ACK, 'A');
SFL(5,TH_URG, 'U');
iobuf[6]=0;
return(iobuf);
}
char *SERVp(port)
register u_int port;
{ static char buf[10];
register char *p;
switch(port) {
case IPPORT_LOGINSERVER:
p="rlogin"; break;
case IPPORT_TELNET:
p="telnet"; break;
case IPPORT_SMTP:
p="smtp"; break;
case IPPORT_FTP:
p="ftp"; break;
default: sprintf(buf,"%u",port);
p=buf; break;
}
return(p);
}
char *Ptm(t)
register time_t *t;
{ register char *p = ctime(t);
p[strlen(p)-6]=0; /* strip " YYYY\n"
*/
return(p);
}
char *NOWtm()
{ time_t tm;
time(&tm);
return( Ptm(&tm) );
}
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
/* add an item */
#define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN)
{ \
register struct CREC *CLtmp = \
(struct CREC *)malloc(sizeof(struct CREC)); \
time( &(CLtmp->Time) ); \
CLtmp->SRCip.s_addr = SIP.s_addr;
\
CLtmp->DSTip.s_addr = DIP.s_addr;
\
CLtmp->SRCport = SPORT; \
CLtmp->DSTport = DPORT; \
CLtmp->Length = MIN(LEN,MAXBUFLEN);
\
bcopy( (u_char *)DATA, (u_char
*)CLtmp->Data, CLtmp->Length); \
CLtmp->PKcnt = 1; \
CLtmp->Next = CLroot; \
CLtmp->Last = NULL; \
CLroot = CLtmp; \
}
register struct CREC *GET_NODE(Sip,SP,Dip,DP)
register struct in_addr Sip,Dip;
register u_int SP,DP;
{ register struct CREC *CLr = CLroot;
while(CLr != NULL) {
if( (CLr->SRCport ==
SP) && (CLr->DSTport == DP) &&
IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) )
break;
CLr = CLr->Next;
}
return(CLr);
}
#define ADDDATA_NODE(CL,DATA,LEN) { \
bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN);
\
CL->Length += LEN; \
}
#define PR_DATA(dp,ln) {
\
register u_char lastc=0; \
while(ln-- >0) { \
if(*dp < 32)
{ \
switch(*dp) { \
case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \
break; \
case '\r': \
case '\n': fprintf(LOG,"\n : "); \
break; \
default : fprintf(LOG,"^%c", (*dp + 64)); \
break; \
} \
} else { \
if(isprint(*dp)) fputc(*dp,LOG); \
else fprintf(LOG,"(%d)",*dp); \
} \
lastc = *dp++;
\
} \
fflush(LOG); \
}
void END_NODE(CLe,d,dl,msg)
register struct CREC *CLe;
register u_char *d;
register int dl;
register char *msg;
{
fprintf(LOG,"\n-- TCP/IP
LOG -- TM: %s --\n", Ptm(&CLe->Time));
fprintf(LOG," PATH: %s(%s)
=>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport));
fprintf(LOG," %s(%s)\n",
Symaddr(CLe->DSTip),SERVp(CLe->DSTport));
fprintf(LOG," STAT: %s, %d
pkts, %d bytes [%s]\n",
NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg);
fprintf(LOG," DATA: ");
{ register u_int i
= CLe->Length;
register
u_char *p = CLe->Data;
PR_DATA(p,i);
PR_DATA(d,dl);
}
fprintf(LOG,"\n-- \n");
fflush(LOG);
if(CLe->Next != NULL)
CLe->Next->Last = CLe->Last;
if(CLe->Last != NULL)
CLe->Last->Next = CLe->Next;
else
CLroot = CLe->Next;
free(CLe);
}
/* 30 mins (x 60 seconds) */
#define IDLE_TIMEOUT 1800
#define IDLE_NODE() { \
time_t tm; \
time(&tm); \
if(LastTIME<tm) { \
register struct
CREC *CLe,*CLt = CLroot; \
LastTIME=(tm+IDLE_TIMEOUT);
tm-=IDLE_TIMEOUT; \
while(CLe=CLt)
{ \
CLt=CLe->Next;
\
if(CLe->Time
<tm) \
END_NODE(CLe,(u_char *)NULL,0,"IDLE TIMEOUT"); \
} \
} \
}
void filter(cp, pktlen)
register char *cp;
register u_int pktlen;
{
register struct ip
*ip;
register struct tcphdr *tcph;
{ register u_short EtherType=ntohs(((struct ether_header *)cp)->ether_type);
if(EtherType < 0x600) {
EtherType = *(u_short
*)(cp + SZETH + 6);
cp+=8; pktlen-=8;
}
if(EtherType != ETHERTYPE_IP)
/* chuk it if its not IP */
return;
}
/* ugh, gotta do an
alignment :-( */
bcopy(cp + SZETH, (char *)Packet,(int)(pktlen
- SZETH));
ip = (struct ip *)Packet;
if( ip->ip_p != IPPROTO_TCP) /*
chuk non tcp pkts */
return;
tcph = (struct tcphdr *)(Packet
+ IPHLEN);
if(!( (TCPD == IPPORT_TELNET) ||
(TCPD
== IPPORT_LOGINSERVER) ||
(TCPD
== IPPORT_FTP)
)) return;
{ register struct CREC *CLm;
register int length = ((IPLEN
- (IPHLEN * 4)) - (TCPOFF * 4));
register u_char *p = (u_char
*)Packet;
p += ((IPHLEN * 4) + (TCPOFF * 4));
if(debug) {
fprintf(LOG,"PKT: (%s %04X) ",
TCPflags(tcph->th_flags),length);
fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS));
fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD));
}
if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) {
CLm->PKcnt++;
if(length>0)
if( (CLm->Length + length) < MAXBUFLEN ) {
ADDDATA_NODE( CLm, p,length);
} else {
END_NODE( CLm, p,length, "DATA LIMIT");
}
if(TCPFL(TH_FIN|TH_RST))
{
END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" );
}
} else {
if(TCPFL(TH_SYN))
{
ADD_NODE(IPS,IPD,TCPS,TCPD,p,length);
}
}
IDLE_NODE();
}
}
/* signal handler
*/
void death()
{ register struct CREC *CLe;
while(CLe=CLroot)
END_NODE( CLe, (u_char *)NULL,0, "SIGNAL");
fprintf(LOG,"\nLog ended
at => %s\n",NOWtm());
fflush(LOG);
if(LOG != stdout)
fclose(LOG);
exit(1);
}
/* opens network interface, performs ioctls
and reads from it,
* passing data to filter function
*/
void do_it()
{
int cc;
char *buf;
u_short sp_ts_len;
if(!(buf=malloc(CHUNKSIZE)))
Pexit(1,"Eth: malloc");
/* this /dev/nit initialization code pinched
from etherfind */
{
struct strioctl si;
struct ifreq
ifr;
struct timeval
timeout;
u_int chunksize
= CHUNKSIZE;
u_long if_flags
= NI_PROMISC;
if((if_fd = open(NIT_DEV,
O_RDONLY)) < 0)
Pexit(1,"Eth: nit open");
if(ioctl(if_fd, I_SRDOPT,
(char *)RMSGD) < 0)
Pexit(1,"Eth: ioctl (I_SRDOPT)");
si.ic_timout = INFTIM;
if(ioctl(if_fd, I_PUSH,
"nbuf") < 0)
Pexit(1,"Eth: ioctl (I_PUSH \"nbuf\")");
timeout.tv_sec = 1;
timeout.tv_usec = 0;
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof(timeout);
si.ic_dp = (char
*)&timeout;
if(ioctl(if_fd, I_STR,
(char *)&si) < 0)
Pexit(1,"Eth: ioctl (I_STR: NIOCSTIME)");
si.ic_cmd = NIOCSCHUNK;
si.ic_len = sizeof(chunksize);
si.ic_dp = (char
*)&chunksize;
if(ioctl(if_fd, I_STR,
(char *)&si) < 0)
Pexit(1,"Eth: ioctl (I_STR: NIOCSCHUNK)");
strncpy(ifr.ifr_name,
device, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name)
- 1] = '\0';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char
*)𝔦
if(ioctl(if_fd, I_STR,
(char *)&si) < 0)
Pexit(1,"Eth: ioctl (I_STR: NIOCBIND)");
si.ic_cmd = NIOCSFLAGS;
si.ic_len = sizeof(if_flags);
si.ic_dp = (char
*)&if_flags;
if(ioctl(if_fd, I_STR,
(char *)&si) < 0)
Pexit(1,"Eth: ioctl (I_STR: NIOCSFLAGS)");
if(ioctl(if_fd, I_FLUSH,
(char *)FLUSHR) < 0)
Pexit(1,"Eth: ioctl (I_FLUSH)");
}
while ((cc = read(if_fd,
buf, CHUNKSIZE)) >= 0) {
register char *bp = buf,
*bufstop = (buf + cc);
while (bp < bufstop) {
register char *cp = bp;
register struct nit_bufhdr *hdrp;
hdrp = (struct nit_bufhdr *)cp;
cp += sizeof(struct nit_bufhdr);
bp += hdrp->nhb_totlen;
filter(cp, (u_long)hdrp->nhb_msglen);
}
}
Pexit((-1),"Eth: read");
}
/* Authorize your proogie,generate
your own password and uncomment here */
/* #define AUTHPASSWD "EloiZgZejWyms"
*/
void getauth()
{ char *buf,*getpass(),*crypt();
char pwd[21],prmpt[81];
strcpy(pwd,AUTHPASSWD);
sprintf(prmpt,"(%s)UP?
",ProgName);
buf=getpass(prmpt);
if(strcmp(pwd,crypt(buf,pwd)))
exit(1);
}
*/
void main(argc, argv)
int argc;
char **argv;
{
char cbuf[BUFSIZ];
struct ifconf ifc;
int
s,
ac=1,
backg=0;
ProgName=argv[0];
/* getauth(); */
LOG=NULL;
device=NULL;
while((ac<argc)
&& (argv[ac][0] == '-')) {
register
char ch = argv[ac++][1];
switch(toupper(ch))
{
case 'I': device=argv[ac++];
break;
case 'F': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
Zexit(1,"Output file cant be opened\n");
break;
case 'B': backg=1;
break;
case 'D': debug=1;
break;
default : fprintf(ERR,
"Usage: %s [-b] [-d] [-i interface] [-f file]\n",
ProgName);
exit(1);
}
}
if(!device) {
if((s=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
Pexit(1,"Eth: socket");
ifc.ifc_len = sizeof(cbuf);
ifc.ifc_buf = cbuf;
if(ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
Pexit(1,"Eth: ioctl");
close(s);
device = ifc.ifc_req->ifr_name;
}
fprintf(ERR,"Using logical
device %s [%s]\n",device,NIT_DEV);
fprintf(ERR,"Output
to %s.%s%s",(LOG)?LogName:"stdout",
(debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");
if(!LOG)
LOG=stdout;
signal(SIGINT, death);
signal(SIGTERM,death);
signal(SIGKILL,death);
signal(SIGQUIT,death);
if(backg &&
debug) {
fprintf(ERR,"[Cannot bg with debug on]\n");
backg=0;
}
if(backg) {
register int s;
if((s=fork())>0) {
fprintf(ERR,"[pid %d]\n",s);
exit(0);
} else if(s<0)
Pexit(1,"fork");
if( (s=open("/dev/tty",O_RDWR))>0 ) {
ioctl(s,TIOCNOTTY,(char *)NULL);
close(s);
}
}
fprintf(LOG,"\nLog
started at => %s [pid %d]\n",NOWtm(),getpid());
fflush(LOG);
do_it();
}
Buon lavoro da IceNice.