zoukankan      html  css  js  c++  java
  • 利用libpcap分析网络上的数据包(入门级)

    本文可任意转载,但请保留作者及出处
    作者:rainfish
    出处:http://blog.csdn.net/bat603/
    经过几天的突击,终于明白了怎样在局域网内抓包,这可是我多年来的梦想。首先说说我的学习过程,一开始从网上搜索了关于sniffer大量资料,大致学会了,可是仔细分析结果发现,都是本机上的数据包,而不是整个局域网的。于是又查资料,在 linuxsir上有高人指点,说,现在局域网内都是交换机联接,而不是以前的Hub所以,如果要抓整个局域网的数据包,必须用libpcap,于是又查了许多关于Libpcap的资料,经过一天的努力,总算稍微有点眉目了。总结手里的资料,它们都在讲怎样用libpcap抓包,而没有讲怎样去分析包,所以在下就写了一个小小的例子,去分析数据包里的具体信息,如果有不正确的地方,敬请指正。
    关于libpcap的使用方法,请参考我收集的的资料
    http://blog.csdn.net/bat603/archive/2006/09/04/1175729.aspx
    http://blog.csdn.net/bat603/archive/2006/09/04/1176251.aspx
    下边这个比较深奥
    http://blog.csdn.net/bat603/archive/2006/09/04/1175271.aspx

    源代码及解释
    /**************************************************************
    ********************rainfish**********************************
    ***************http://blog.csdn.net/bat603/**********************
    **********本文可任意转载,但请保留作者及出处*****************/

    //该程序使用方法:./exe_your_file  numpacket
    #include <stdio.h>
    #include <pcap.h>
    /* if this gives you an error try pcap/pcap.h 里面有相应的数据结构一般在/usr/include/中*/

    #include <stdlib.h>
    #include <errno.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netinet/if_ether.h>
    #include <linux/ip.h>
    #include <linux/tcp.h>//注意使用的ip、tcp数据结构,至于它们和 <netinet/ip.h | tcp.h>的区别,我也弄不清楚。

    /*回调函数,int pcap_loop(pcap_t *p, int cnt,
              pcap_handler callback, u_char *user)调用的
    这里需要说明的是,关于参数 pkthdr、packet的说明,好多资料都没有进行解释,在这里我只能尝试的去解释
    当执行pcap_loop,会自动调用回调函数,pcap_t *p是调用者传递的,参看下面例子,而pkthdr(libpcap 自定义数据包头部),packet(捕获的书据包)就会相应得到,而不用用户操作。下面的例子也能证明这一点。我实在不敢确定,因为没有找到相应的文档
    */
    void my_callback(u_char *userless, const struct pcap_pkthdr *pkthdr, 
                        const u_char *packet)
    {
        struct in_addr addr;
        struct iphdr *ipptr;
        struct tcphdr *tcpptr;//太次片,,ip,tcp数据结构
        char *data;
            
        pcap_t *descr = (pcap_t*)userless;//捕获网络数据包的数据包捕获描述字
        //const u_char *packet;
        struct pcap_pkthdr hdr = *pkthdr;//(libpcap 自定义数据包头部),
        struct ether_header *eptr;//以太网字头
        u_char *ptr;
        int i;
     
        if (packet == NULL)//packet里面有内容,可以证明上面的猜想,
        {
            printf ("Didn't grab packet!/n");
            exit (1);
        }
        printf ("/n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/n");
        printf ("Grabbed packet of length %d/n", hdr.len);
        printf ("Received at : %s/n", ctime((const time_t*)&hdr.ts.tv_sec));
        printf ("Ethernet address length is %d/n", ETHER_HDR_LEN);
        
        eptr = (struct ether_header*)packet;//得到以太网字头
        
        if (ntohs(eptr->ether_type) == ETHERTYPE_IP)
        {
            printf ("Ethernet type hex:%x dec:%d is an IP packet/n",
                        ntohs(eptr->ether_type), ntohs(eptr->ether_type));
        }
        else 
        {
            if (ntohs(eptr->ether_type) == ETHERTYPE_ARP)
            {
                printf ("Ethernet type hex:%x dec:%d is an ARP packet/n",
                            ntohs(eptr->ether_type), ntohs(eptr->ether_type));
            }
            else
            {
                printf ("Ethernet type %x not IP/n", ntohs(eptr->ether_type));
                exit (1);
            }
        }
            
        ptr = eptr->ether_dhost;
        i = ETHER_ADDR_LEN;
        printf ("i=%d/n", i);
        printf ("Destination Address: ");
        do
        {
            printf ("%s%x", (i == ETHER_ADDR_LEN)?"":":", *ptr++);
        }while(--i>0);
        printf ("/n");
        //printf ("%x/n",ptr);
        
        ptr = eptr->ether_shost;
        i = ETHER_ADDR_LEN;
        printf ("Source Address: ");
        do
        {
            printf ("%s%x", (i == ETHER_ADDR_LEN)?"":":", *ptr++);
        }while(--i>0);
        printf ("/n");
        printf ("Now decoding the IP packet./n");
        ipptr = (struct iphdr*)    (packet+sizeof(struct ether_header));//得到ip包头
        
        printf ("the IP packets total_length is :%d/n", ipptr->tot_len);
        printf ("the IP protocol is %d/n", ipptr->protocol);
        addr.s_addr = ipptr->daddr;
        printf ("Destination IP: %s/n", inet_ntoa(addr));    
        addr.s_addr = ipptr->saddr;
        printf ("Source IP: %s/n", inet_ntoa(addr));
        
        printf ("Now decoding the TCP packet./n");
        tcpptr = (struct iphdr*)(packet+sizeof(struct ether_header)
                                        +sizeof(struct iphdr));//得到tcp包头
        printf ("Destination port : %d/n", tcpptr->dest);
        printf ("Source port : %d/n", tcpptr->source);
        printf ("the seq of packet is %d/n", tcpptr->seq);
    //以上关于ip、tcp的结构信息请查询/usr/include/linux/ip.h | tcp.h
        
        data = (char*)(packet+sizeof(struct ether_header)+sizeof(struct iphdr)
                                        +sizeof(struct tcphdr));//得到数据包里内容,不过一般为乱码。
        
        printf ("the content of packets is /n%s/n",data);
    }
    int main(int argc, char **argv)
    {
        int i;
        char *dev;
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *descr;
        const u_char *packet;
        struct pcap_pkthdr hdr;
        struct ether_header *eptr;
        
        if (argc != 2)
        {
            fprintf (stdout, "Usage: %s numpackets/n", argv[0]);
            return 0;
        }
        
        dev = pcap_lookupdev (errbuf);
        if (dev == NULL)
        {
            printf ("%s/n", errbuf);
            exit (1);
        }
        
        descr = pcap_open_live (dev, BUFSIZ, 1, -1, errbuf);
        //第三个参数,1为混杂模式;0为非混杂模式
        //BUFSIZ同PCAP_ERRBUF_SIZE一样,均为库文件已经定义好的,不推荐使用
        if (descr == NULL)
        {
            printf ("pcap_open_live(): %s/n", errbuf);
            exit (1);
        }
        pcap_loop (descr, atoi(argv[1]), my_callback, NULL);//调用回调函数
        
     
            
        printf("Hello world/n");
        return (0);
    }
    关于过滤机制,以后再写

  • 相关阅读:
    vue + ElementUI 的横向表格代码
    localStorage.getItem
    字符串分割与数组的分割 split()VSsplice()&slice()
    ES6 Class 的基本语法
    e6 6 Symbol
    ES6 Iterator 和 for...of 循环
    ES6 数组的扩展
    element-ui上传一张图片后隐藏上传按钮
    图片上传预览原理及实现
    Winform的一些控件说明
  • 原文地址:https://www.cnblogs.com/lihaibo-Leao/p/3951321.html
Copyright © 2011-2022 走看看