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是一個開源項目,功能強大的數據截取分析工具。
關於TCP/IP數據包的截取和分析(摘自安全焦點論壇,原作:ilsy)