zoukankan      html  css  js  c++  java
  • winpcap编程设置过滤器之指定获取某个网站的数据

    下面,我将以 乱世隋唐页游 为例,通过编码获取这里面的数据。

    游戏图:

    我是乱世隋唐的网址是:www.917st.com

    这个是官网网址的服务器地址。  42.62.0.14

    我玩的游戏服是84区。网址是:www.s84.917st.com

    我所在区的服务器地址是: 42.62.0.7

    winpcap里有一个过滤器字符串。凡是发送给这个服务器的内容,我都要获取到。我们需要设置它为:dst host 42.62.0.7    表示目标主机地址是42.62.0.7

    如果我要获取从这个服务器发来的数据,需要设置过滤器字符串:src host 42.62.0.7

    关于字符串过滤器的语法,winpcap官网有,我这里不想讲。

    现在开始编程实现获取这个游戏的数据:

    #include "pcap.h"
    
    
    int main()
    {
        pcap_if_t *alldevs;
        pcap_if_t *d;
        int inum;
        int i=0;
        pcap_t *adhandle;
        int res;
        char errbuf[PCAP_ERRBUF_SIZE];
        struct tm *ltime;
        char timestr[16];
        struct pcap_pkthdr *header;
        const u_char *pkt_data;
        time_t local_tv_sec;
        u_int netmask;
        char packet_filter[] = "dst host 42.62.0.7";
        struct bpf_program fcode;
    
        /* 获取本机设备列表 */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
        {
            fprintf(stderr,"Error in pcap_findalldevs: %s
    ", errbuf);
            exit(1);
        }
        
        /* 打印列表 */
        for(d=alldevs; d; d=d->next)
        {
            printf("%d. %s", ++i, d->name);
            if (d->description)
                printf(" (%s)
    ", d->description);
            else
                printf(" (No description available)
    ");
        }
        
        if(i==0)
        {
            printf("
    No interfaces found! Make sure WinPcap is installed.
    ");
            return -1;
        }
        
        printf("Enter the interface number (1-%d):",i);
        scanf("%d", &inum);
        
        if(inum < 1 || inum > i)
        {
            printf("
    Interface number out of range.
    ");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
        
        /* 跳转到已选中的适配器 */
        for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
        
        /* 打开设备 */
        if ( (adhandle= pcap_open(d->name,          // 设备名
                                  65536,            // 要捕捉的数据包的部分 
                                                    // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
                                  PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
                                  1000,             // 读取超时时间
                                  NULL,             // 远程机器验证
                                  errbuf            // 错误缓冲池
                                  ) ) == NULL)
        {
            fprintf(stderr,"
    Unable to open the adapter. %s is not supported by WinPcap
    ", d->name);
            /* 释放设列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
        
        printf("
    listening on %s...
    ", d->description);
        
        
        /* 设置过滤器 */
        if (d->addresses != NULL)
            /* 获取接口第一个地址的掩码 */
            netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
        else
            /* 如果这个接口没有地址,那么我们假设这个接口在C类网络中 */
            netmask=0xffffff; 
        if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)>=0)
        {
            //设置过滤器
            if (pcap_setfilter(adhandle, &fcode)<0)
            {
                fprintf(stderr,"
    Error setting the filter.
    ");
                /* 释放设备列表 */
                pcap_freealldevs(alldevs);
                return -1;
            }
        }
        else
        {
                fprintf(stderr,"
    Error setting the filter.
    ");
                /* 释放设备列表 */
                pcap_freealldevs(alldevs);
                return -1;
        }
    
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
    
        /* 获取数据包 */
        while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){
            
            if(res == 0)
                /* 超时时间到 */
                continue;
            
            /* 将时间戳转换成可识别的格式 */
            local_tv_sec = header->ts.tv_sec;
            ltime=localtime(&local_tv_sec);
            strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
            
            printf("%s,%.6d len:%d
    ", timestr, header->ts.tv_usec, header->len);
        }
        
        if(res == -1){
            printf("Error reading the packets: %s
    ", pcap_geterr(adhandle));
            return -1;
        }
        
        return 0;
    }

    程序运行截图:

    我这里获取到四个本地网络适配器。但是实质上我的笔记本只有俩个物理网卡,一个无线,一个有线。后面3,4选项是虚拟机模拟出来的,这里不用管。因为我目前还没用虚拟机。1选项,表示获取的是物理有线网卡,2选项,表示获取的是物理无线网卡。我目前上网用无线WIFI   ,所以选择2

    我现在在向游戏里说话,说80个0.,字符0的ascii码为0x30   那么在获取到的数据包里应该会出现80个0x30

    运行截图:

    游戏截图:

    果然出现了我们预期的结果,出现了80个 30

    我现在说一下本人获取包一些经验,用在世界说话,获取包的结构。

    这里的结果,可以得知:

    数据的前五个字节是 06 01 06 81 21

    数据的后五个字节是 02 0a 0b 01 15

    也就是说,凡是在这个中间的都是说话的内容。

    现在,我决定在做一个操作,就是买粮食,127个

    如图:

    127的十六进制是0x7F,   如果数据没加密的话,那么就可以获取到数据 0x7F 

    但是数据包里的十六进制数据像0x7F的数据有很多,怎么确定这个数据就是我们购买数量的数据呢,其实很简单。就是根据它的前后数据判断就可以得出了。

    只有这一个数据,对我们太有利了,哈哈。 【23 04 01 04】 7f 【04 0a 02 02 0a】

    现在我准备购买126个数量的粮食,十六进制是7E,在截获包。

    截获的包:

    哈哈,已经找到了,那么我们就可以,我们总结

    凡是出现在【04 01 04 7e】 和【04 0a 02 02 0a】之间的数据都是购买粮食的数量

    #include "pcap.h"
    
    
    int main()
    {
        pcap_if_t *alldevs;
        pcap_if_t *d;
        int inum;
        int i=0;
        pcap_t *adhandle;
        int res;
        char errbuf[PCAP_ERRBUF_SIZE];
        struct tm *ltime;
        char timestr[16];
        struct pcap_pkthdr *header;
        const u_char *pkt_data;
        time_t local_tv_sec;
        u_int netmask;
        char packet_filter[] = "dst host 42.62.0.7";
        struct bpf_program fcode;
    
        /* 获取本机设备列表 */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
        {
            fprintf(stderr,"Error in pcap_findalldevs: %s
    ", errbuf);
            exit(1);
        }
        
        /* 打印列表 */
        for(d=alldevs; d; d=d->next)
        {
            printf("%d. %s", ++i, d->name);
            if (d->description)
                printf(" (%s)
    ", d->description);
            else
                printf(" (No description available)
    ");
        }
        
        if(i==0)
        {
            printf("
    No interfaces found! Make sure WinPcap is installed.
    ");
            return -1;
        }
        
        printf("Enter the interface number (1-%d):",i);
        scanf("%d", &inum);
        
        if(inum < 1 || inum > i)
        {
            printf("
    Interface number out of range.
    ");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
        
        /* 跳转到已选中的适配器 */
        for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
        
        /* 打开设备 */
        if ( (adhandle= pcap_open(d->name,          // 设备名
                                  65536,            // 要捕捉的数据包的部分 
                                                    // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
                                  PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
                                  1000,             // 读取超时时间
                                  NULL,             // 远程机器验证
                                  errbuf            // 错误缓冲池
                                  ) ) == NULL)
        {
            fprintf(stderr,"
    Unable to open the adapter. %s is not supported by WinPcap
    ", d->name);
            /* 释放设列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
        
        printf("
    listening on %s...
    ", d->description);
        
        
        /* 设置过滤器 */
        if (d->addresses != NULL)
            /* 获取接口第一个地址的掩码 */
            netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
        else
            /* 如果这个接口没有地址,那么我们假设这个接口在C类网络中 */
            netmask=0xffffff; 
        if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)>=0)
        {
            //设置过滤器
            if (pcap_setfilter(adhandle, &fcode)<0)
            {
                fprintf(stderr,"
    Error setting the filter.
    ");
                /* 释放设备列表 */
                pcap_freealldevs(alldevs);
                return -1;
            }
        }
        else
        {
                fprintf(stderr,"
    Error setting the filter.
    ");
                /* 释放设备列表 */
                pcap_freealldevs(alldevs);
                return -1;
        }
    
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
    
        /* 获取数据包 */
        while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){
            
            if(res == 0)
                /* 超时时间到 */
                continue;
            
            /* 将时间戳转换成可识别的格式 */
            local_tv_sec = header->ts.tv_sec;
            ltime=localtime(&local_tv_sec);
            strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
            
            printf("%s,%.6d len:%d
    ", timestr, header->ts.tv_usec, header->len);
            
            /* 打印包 */
            int len = header->caplen + 1;
            for (i=1;i<len; i++)
            {
                printf("%.2x ", pkt_data[i-1]);
                if(pkt_data[i-1]==0x7e)
                {
                    printf("==找到了后五位数据是,%.2x %.2x %.2x %.2x %.2x
    ",pkt_data[i],pkt_data[i+1],pkt_data[i+2],pkt_data[i+3],pkt_data[i+4]);
                }
                if ( (i % 16) == 0) 
                    printf("
    ");
    
            }
            
            printf("
    -----------------------------------------------------------------
    "); 
        }
        
        if(res == -1){
            printf("Error reading the packets: %s
    ", pcap_geterr(adhandle));
            return -1;
        }
        
        return 0;
    }

    本人不会贴发包的源码,以防有人用作非法用途。如果想要发送封包,请自行学习winpcap

  • 相关阅读:
    几种基本样式,背景图,字体,下划线,行高垂直等
    网页主菜单,横向
    DOM操作
    递归的小例题
    学习两个星期后做的第一个网页
    Js的语法和循环
    JS
    75 int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数。[2行核心代码]
    74 使用BitSet输出数组中的重复元素
    73 [面试题]交换一个整数的二进制表示的奇偶位(swapOddEvenBits)
  • 原文地址:https://www.cnblogs.com/dzqdzq/p/3302994.html
Copyright © 2011-2022 走看看