zoukankan      html  css  js  c++  java
  • 原始数据包的分析

     学习NDIS一段时间了,不过还是毫无头绪,理论都能明白,可是不知道怎么下手去做,网上没有没有太详细的教程。我是比较笨,而且比较懒的。:)

      所以准备暂缓NDIS网络和驱动方面的学习,等今后遇见师父了再请教之,好运~

      NDIS中的网络数据都是原始的,即没有经过主机协议栈处理的网络数据,如果学习网络协议的话,我觉得研究原始数据包还是挺合适的。

      Socket通信中,主机A与主机B之间通信,Socket接收到的内容都是通信的内容,没有附带主机A或主机B的信息,这点可以回想最开始学习Socket编程的时候,主机A发送“Hello,mydearfriend.”,那么主机B收到的确实是“Hello,mydearfriend.”。不像原始数据包中,还会带有以太网帧头、IP头、TCP/UDP头,然后才是通信的内容。所以呢,当我们通过NDIS获取到了原始数据包之后,应该按照现在的网络通信模型对原始数据包进行解析。

    =============================================================================================

      常用的以太网MAC帧格式有两种,标准:DIXEthernetV2标准(即以太网V2标准)和IEEE的802.3标准。现在使用最多的是以太网V2的MAC帧格式。该标准由5个字段组成:6字节的目的地址、6字节的源地址、2字节的类型(用来标识上一层的协议类型,例如:0x0800表示上层使用是IP数据报)、46字节至1500字节长度不等的IP数据报,以及4字节的帧检验序列(FCS)。分析每一帧可以得到此数据包的源MAC地址和目的MAC地址,并且可以得到IP数据报的完整内容。

      IP数据报的第4至7位是IP首部长度,该字段可以用来准确定位上层协议的起始位置(例如:TCP的首部)。第10字节是协议字段,指出该IP数据报携带的数据使用何种协议,常用的协议字段如表1所示。第13至16字节是源IP地址,第17至20字节是目的IP地址。因此可以据此解析出该数据包的源IP地址和目的IP地址。

    表1常用的IP协议和相应的字段值

    协议名

    ICMP

    IGMP

    TCP

    EGP

    IGP

    UDP

    IPv6

    OSPF

    协议字段值

    1

    3

    6

    8

    9

    17

    41

    89

      TCP报文段的第1至2字节是源端口号,第3至4字节是目的端口号。第13字节的前4位是数据偏移,该字段实际上指出了TCP报文段的首部长度。如果TCP承载的是HTTP协议,则可以据此定位HTTP协议的起始位置。系统处理时,如果分析是HTTP协议,则提取出HTTP的内容,以明文显示。而可以直接显示HTTP报文信息的原因是:HTTP是应用层协议,使用面向连接的TCP作为传输层协议,在向下层传递时是以明文的方式直接传递,即TCP在HTTP报文前加TCP头封装HTTP报文。因此,只要把捕获到的数据包依次剥去MAC头、IP头、TCP头,就可以显示HTTP报文的内容了。

      HTTP报文分为两种:请求报文和响应报文。

      对于判断是否为HTTP报文,目前还没有快速有效的方法。传统的方法依据:①传送HTTP报文前是否有TCP的三次握手;②判断数据包中是否含有诸如“GET”、“HTTP/1.1”等关键字。对于这两种方法,第①点需要一定的空间开销,要判断TCP承载的是否为HTTP报文,需要分配一定的空间存储前3个数据包的相关信息(实际并不需要存储3个数据包的全部内容,但是即便是若干比特的信息,也会增加NPF的负担),这给NPF(NetgroupPacketFilter)的运行速率和存储器带来挑战;对于第②点,由于HTTP是面向文本的,因此在报文中的每一个字段都是一些ASCII码串,因而各个字段的长度都是不确定的。请求报文中除了“GET”方法外,还有7种常用的方法,如果要一一模式匹配来确定是否是HTTP报文,显然会造成很大的时间开销。此外,响应报文含“HTTP/1.1”(或HTTP/1.0)的版本号,这个字段在请求报文中也有,具体的版本是1.1还是1.0则是不确定的。因此,综合考虑时间和空间的开销,本文采取模式匹配“HTTP”的方法来判断是否为HTTP报文。具体方法是:捕获到的数据包从TCP的尾部(HTTP的第一个字节)开始匹配“HTTP”,如果匹配成功,则认为是HTTP报文,否则就不是。这种方法存在的问题是:①如果TCP承载的是FTP或SMTP等其他应用层协议,恰好在某个部分也含有“HTTP”字样,则会误判为HTTP报文。但是由于基于HTTP协议的Web服务已经成为Internet的主流,非HTTP协议只占到小部分,因此误判的几率很小。系统测试期间,还未发现此类误判问题,用户界面显示的明文信息表明:确为HTTP协议的请求报文或响应报文。②该方法本身不存在“漏判”,因为所有的HTTP报文都含有“HTTP”字样,而抓到的数据包只要含有“HTTP”字样,就被过滤认为HTTP报文。但是,由于该方法需要一定的时间开销,可能来不及匹配后续的数据包而造成广义上的“漏判”。这个问题通过编写高效的模式匹配算法可以得到一定的改进,但是不能解决根本问题。根本问题在于匹配速度和内核的存储器容量的限制。

      对于过滤用户指定的IP地址和端口号,用户输入的IP地址为char[]字符数组型,而且是用标准的Internet的“.”间隔格式来表示一个Internet地址,而捕获得到的数据包拆包后的IP地址是网络字节的,因此不可直接比较。本文的方法是:首先用inet_addr()将用户输入的IP地址转换成一个无符号长整型数(实际上是in_addr类型),然后与抓到的数据包的4字节IP地址一一比较,即可过滤出用户指定的IP地址。对于端口号亦可类似处理。

    =============================================================================================

      这里仅对原始数据包中HTTP的解析,如果是原始数据包中其他应用层的协议解析,也可参考此思路。

      说明:这里例举原始数据包中HTTP的解析的原因是,我想做一个防火墙,不仅可以屏蔽某个网站(这里有两种方法:①屏蔽该网站的IP地址②主机发送到该网站的HTTP请求时,自己通过程序伪造一个HTTP应答在网站的主机返回HTTP应答之前返回给浏览器,毕竟和“127.0.0.1”比其他IP地址通信更快。可能第二种方法有问题。),还可以屏蔽某网站的某个页面(方法可参考屏蔽某个网站的方法②)。

    【参考资料感谢作者】
    基于WinPcap的数据包捕获和分析系统的设计与实现:http://www.paper.edu.cn

    #define ETHERTYPE_IP    0x0800
    #define ETHERTYPE_ARP   0x0806
    
    typedef struct _ETHeader         // 14 bytes
    {
        UCHAR    dhost[6];            // 目的MAC地址destination mac address
        UCHAR    shost[6];            // 源MAC地址source mac address
        USHORT    type;                // 下层协议类型,如IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)等
    } ETHeader, *PETHeader;
    
    #define ARPHRD_ETHER     1
    
    // ARP协议opcodes
    #define    ARPOP_REQUEST    1        // ARP 请求    
    #define    ARPOP_REPLY        2        // ARP 响应
    
    typedef struct _ARPHeader        // 28字节的ARP头
    {
        USHORT    hrd;                //    硬件地址空间,以太网中为ARPHRD_ETHER
        USHORT    eth_type;            //  以太网类型,ETHERTYPE_IP ??
        UCHAR    maclen;                //    MAC地址的长度,为6
        UCHAR    iplen;                //    IP地址的长度,为4
        USHORT    opcode;                //    操作代码,ARPOP_REQUEST为请求,ARPOP_REPLY为响应
        UCHAR    smac[6];            //    源MAC地址
        UCHAR    saddr[4];            //    源IP地址
        UCHAR    dmac[6];            //    目的MAC地址
        UCHAR    daddr[4];            //    目的IP地址
    } ARPHeader, *PARPHeader;
    
    
    typedef union _IPADDRESS{
        ULONG ip;
        UCHAR a[4];
    }IPADDRESS, *PIPADDRESS;
    
    //Protocol
    typedef struct _IPHeader        // 20
    {
        UCHAR     iphVerLen;      // 版本号和头长度(各占4位)
        UCHAR     ipTOS;          // 服务类型 
        USHORT    ipLength;       // 封包总长度,即整个IP报的长度
        USHORT    ipID;              // 封包标识,惟一标识发送的每一个数据报
        USHORT    ipFlags;          // 标志
        UCHAR     ipTTL;          // 生存时间,就是TTL
        UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
        
    #define PROTO_ICMP    1
    #define PROTO_IGMP    2
    #define PROTO_TCP     6
    #define PROTO_UDP     17
        USHORT    ipChecksum;     // 校验和
        IPADDRESS srcip;
        IPADDRESS destip;
    } IPHeader, *PIPHeader; 
    
    
    //  define the tcp flags....
    #define   TCP_FIN   0x01
    #define   TCP_SYN   0x02
    #define   TCP_RST   0x04
    #define   TCP_PSH   0x08
    #define   TCP_ACK   0x10
    #define   TCP_URG   0x20
    #define   TCP_ACE   0x40
    #define   TCP_CWR   0x80
    
    typedef struct _TCPHeader                //20 bytes
    {
        USHORT            sourcePort;            // 16位源端口号
        USHORT            destinationPort;    // 16位目的端口号
        ULONG            sequenceNumber;        // 32位序列号
        ULONG            acknowledgeNumber;    // 32位确认号
        UCHAR            dataoffset;            // 高4位表示数据偏移
        UCHAR            flags;                // 6位标志位
    //FIN - 0x01
    //SYN - 0x02
    //RST - 0x04 
    //PUSH- 0x08
    //ACK- 0x10
    //URG- 0x20
    //ACE- 0x40
    //CWR- 0x80
        USHORT            windows;            // 16位窗口大小
        USHORT            checksum;            // 16位校验和
        USHORT            urgentPointer;        // 16位紧急数据偏移量 
    } TCPHeader, *PTCPHeader;
    
    typedef struct _UDPHeader
    {
        USHORT            sourcePort;        // 源端口号        
        USHORT            destinationPort;// 目的端口号        
        USHORT            len;            // 封包长度
        USHORT            checksum;        // 校验和
    } UDPHeader, *PUDPHeader;
    
    /*tcp_udp校验和尾首部定义*/
    typedef struct Psd_head{
        IPADDRESS sadr;            //源IP地址
        IPADDRESS dadr;            //目的IP地址
        u_char        mbz;            //置空(0)
        u_char      proto;            //协议内型
        u_short    tlen;//TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)
    }Psd_header;
    
    typedef struct _ICMPHeader
    {
        UCHAR   type;
        UCHAR   code;
        USHORT  checksum;
        USHORT  id;
        USHORT  sequence;
        ULONG   timestamp;
    } ICMPHeader, *PICMPHeader;
  • 相关阅读:
    bzoj 3438: 小M的作物
    bzoj 4445 [SCOI2015] 小凸想跑步
    hdu 4899 Hero meet devil
    hdu 4898 The Revenge of the Princess’ Knight
    【NOIP1999】拦截导弹
    【OpenJudge】2991:2011 题解
    【cqbzoj】1785:残缺棋盘上放车的方案数 --状压dp --输入毁一生
    【cqbzoj】:1330 Prime DP(Ahio2001 质数和分解)
    【Openjudge:Noi】7891:一元三次方程求解 c++
    【USACO FEB 2010 SILVER】吃巧克力(Chocolate Eating)
  • 原文地址:https://www.cnblogs.com/RodYang/p/3237981.html
Copyright © 2011-2022 走看看