关于TCP/IP数据包的截取和分析

关于TCP/IP数据包的截取和分析(摘自安全焦点论坛,原作:ilsy)


TCP/IP数据包的截取是一个简单的工作,在Windows 2000/xp下,下面方法可以完成TCP/IP数据包的截获:
1、通过建立rawsocket来完成对TCP/IP数据包的截获。从Windows 2000开始,Winsock 2开始支持原始socket,可以 截获所有经过本机的TCP/IP数据包,支持拨号网络,但对本机向外发送的TCP/IP数据包截获有缺陷。可以从http://www.codeguru.com/Cpp/I-N/network/tcpip/article.php/c5413得到更加详细的信息及演示代码,现在很多基于rawsocket的代码都是参照这篇文章完成的。
2、通过WinPcap Developer's pack来完成对TCP/IP数据包的截获。这个开发包可以很好的在windows 9x/nt/2000/xp下工作,不支持拨号网络。可以从http://winpcap.polito.it/获得更详细的信息和用户手册,在本版的精华版也包括一个介绍这个开发包的文章可以参照。
Windows下对TCP/IP数据包的截获大多通过这两个方法来完成。如果你需要编写一个轻量级的TCP/IP数据包的截取和分析工具,而且只在Windows 2000/xp下工作,你可以选择第一种方法,比较简单,而且不需要另外的驱动;否则,你需要选择第二种方法或其他方法。
在类UNIX系统(比如linux)下,通常使用libpcap(http://www.tcpdump.org/)完成TCP/IP数据包的截取工作,它可以工作在多种操作系统下。

可以从互联网上面搜索到很多Windows下的TCP/IP数据包截取的演示代码,还可以搜索到很多linux下的开源项目,甚至功能完备复杂的大型TCP/IP数据包截取项目。

TCP/IP数据包的分析就比较困难和麻烦了。首先这种分析是基于对TCP/IP协议族的理解之上的,如果你还不了解,《TCP-IP详解卷1:协议》是首先需要翻阅的书籍,如果懒的看,那也不要提什么分析了,呵呵。
截取了一个TCP/IP数据包后,首先分离出IP协议(IP“Internet Protocol”协议是TCP/IP协议族中最为核心的协议,所有的TCP、UDP、ICMP和IGMP数据等都是以IP数据报格式传输的)的头部分,从IP协议头中可以得到很多关键的数据,如IP头的长度、源IP、目的IP、TCP/IP协议类型等,下面演示代码实现这个功能:

typedef struct _IP_HEADER            //定义IP首部
{
      unsigned char    h_lenver;       //4位首部长度+4位IP版本号
    unsigned char    tos;            //8位服务类型TOS
      unsigned short   total_len;      //16位总长度(字节)
    unsigned short   ident;          //16位标识
    unsigned short   frag_and_flags; //3位标志位+13位片偏移
    unsigned char    ttl;            //8位生存时间 TTL
      unsigned char    proto;          //8位协议 (TCP, UDP 或其他)
      unsigned short   checksum;       //16位IP首部校验和
    unsigned int     sourceIP;       //32位源IP地址
    unsigned int     destIP;         //32位目的IP地址
} IP_HEADER;

typedef struct _TCP_HEADER            //定义TCP首部
{
      USHORT th_sport;                  //16位源端口
    USHORT th_dport;                  //16位目的端口
    UINT   th_seq;                    //32位序列号
    UINT   th_ack;                    //32位确认号
    UCHAR  th_lenres;                 //4位首部长度/6位保留字
    UCHAR  th_flag;                   //6位标志位
    USHORT th_win;                    //16位窗口大小
    USHORT th_sum;                    //16位校验和
    USHORT th_urp;                    //16位紧急数据偏移量
} TCP_HEADER;

unsigned short DecodeIPHeader(char *buf)  //IP头解码函数 (得到IP头的长度,其他内容得到方法类似)
{
    IP_HEADER * ipheader;
    unsigned short ipheaderlen;

    ipheader = (IP_HEADER *)buf;
    ipheaderlen = sizeof(unsigned long) * (ipheader->h_lenver & 0xf);
    
    return ipheaderlen;
}

好,现在我们获得了IP头的长度,用类似的方法也可以获得了协议类型等其他数据。假设协议类型是TCP,那么接着就可以从数据包中分离出TCP协议(TCP协议是可靠的端到端协议)头的数据,从TCP协议头中得到很多关键的数据,如源端口、目的端口、数据偏移、控制位等。从目的端口中我们可以简单的(但不一定准确)判断一下跟着的数据是什么协议,如端口是80那么是HTTP协议、端口是21是FTP等(HTTP、FTP等协议都是基于TCP协议实现的)。

unsigned short DecodeIPHeader(char *buf)  //TCP头解码函数 (得到目的端口,其他内容得到方法类似)
{
    TCP_HEADER * tcpheader;
    unsigned short ipheaderlen;

    ipheaderlen = DecodeIPHeader(buf);
    tcpheader = (TCP_HEADER *)(buf + ipheaderlen);
    
    return tcpheader->th_dport;
}

通过类似的方法,得到所有需要的数据。一个正常的TCP连接总是由三次握手开始的,也就是说开始的三个数据包它的数据偏移是0,通过控制位可以知道三次握手的完成状态。接着就是分析接下来的数据了,接下来的数据就有很多变化了,一般情况下针对每一种协议都要写解码函数,可以通过端口和数据的一些标志判断数据包是什么协议的数据包,比如SMB协议开始会有0xff加SMB的标志,当然,这首先一个条件是协议是已知并且公开的,如果一个协议是不公开的,那就需要对使用这个协议的网络应用程序进行分析以确定协议的结构并写出相应的解码函数,这就是更复杂和麻烦的工作了,需要的知识也就更多,就不是本文要解决的问题了。

关于各种协议的解码函数在Windows下我是没有找到公开的源码,但如果有时间和耐心,可以参考下面linux下的开源项目,对编写自己的协议解码还是可能有所帮助。如:

http://www.cpan.org/authors/id/T/TI/TIMPOTTER/NetPacket-0.03.tar.gz
用于基本的IP/TCP/UDP等包解码的模块,剥除各种协议头,抽取各个字段。


http://www.ethereal.com/download.html
Ethereal是一个开源项目,功能强大的数据截取分析工具。

你可能感兴趣的:(学习笔记)