數據包捕獲與分析

本文介紹數據包的捕獲與按照協議格式進行數據包分析。數據包捕獲採用了libpcap抓包框架,能夠分析IP、TCP、UDP、ARP、RARP等類型的數據包。


一、數據包捕獲

數據包的捕獲採用了libpcap函數庫,下面介紹捕獲過程中各函數的使用步驟。


1. 獲取網絡接口

char *pcap_lookupdev(char *errbuf)

用於返回可被pcap_open_live()或pcap_lookupnet()函數調用的網絡設備名指針。如果函數出錯,則返回NULL,同時errbuf中存放相關的錯誤消息。


2. 打開網絡接口

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)

上面這個函數會返回指定接口的pcap_t類型指針,後面的所有操作都要使用這個指針。
第一個參數是第一步獲取的網絡接口字符串,可以直接使用硬編碼。
第二個參數是對於每個數據包,從開頭要抓多少個字節。
第三個參數指定是否打開混雜模式(Promiscuous Mode),0表示非混雜模式,任何其他值表示混合模式。如果要打開混雜模式,那麼網卡必須也要打開混雜模式。
第四個參數指定需要等待的毫秒數,0表示一直等待直到有數據包到來。
第五個參數是存放出錯信息的數組。


3. 設置過濾器

雖然不設置過濾器本實驗也能分析各種協議的數據包,但是設置過濾器能獲取特定的包,增強實驗的目的性。實現這一過程由pcap_compile()與pcap_setfilter()這兩個函數完成。
int pcap_compile(pcap_t *p, strUCt bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)

第一個參數是會話句柄。接下來的是我們存儲被編譯的過濾器版本的地址的引用。再接下來的則是表達式本身,存儲在規定的字符串格式裏。再下邊是一個定義表達式是否被優化的整形量(0爲false,1爲true,標準規定)。最後,我們必須指定應用此過濾器的網絡掩碼。函數返回-1爲失敗,其他的任何值都表明是成功的。表達式被編譯之後就可以使用了。

int pcap_setfilter(pcap_t *p, struct bpf_program *fp)

第一個參數是會話句柄,第二個參數是被編譯表達式版本的引用。


4. 獲取數據包

Libpcap中獲取數據包最常用的函數是int pcap_loop()。
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
此函數提供了抓包工具的核心功能。第一個參數是第2步返回的pcap_t類型的指針。第二個參數是需要抓的數據包的個數,一旦抓到了cnt個數據包,pcap_loop立即返回。負數的cnt表示pcap_loop永遠循環抓包,直到出現錯誤。第三個參數是一個回調函數指針,它必須是如下的形式:
void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
其中:第一個參數是pcap_loop的最後一個參數,當收到足夠數量的包後pcap_loop會調用callback回調函數,同時將pcap_loop()的user參數傳遞給它。第二個參數是收到的數據包的pcap_pkthdr類型的指針。第三個參數是收到的數據包數據。
後面,我們將調用回調函數callback() 來進行數據包的分析,回調函數提供了數據包分析的核心功能。


二、數據包分析

1. 數據包分析原理

在libpcap定義的回調函數中,有一個參數const u_char *packet,它是一個u_char類型的指針,包含了所有被pcap_loop()所嗅探到的包。每一個包其實是一塊連續的內存,packet指針指向這塊內存的起始位置。一個數據包包含許多屬性,因此可以看做一個包含許多成員變量的結構體。事先按照協議的格式定義好結構體,然後用這塊內存裝載,則結構體的成員變量將會與數據包信息一一對應。這樣,就拿到了數據包的信息。
下面是一些數據包的結構體定義。各協議頭部可以自己定義,也可以查看Linux  /usr/include/netinet 下的各種協議頭部的結構體定義。
/* IP header*/
struct ip {
        u_char  ip_vhl;                 /* version << 4 | header length >> 2 */
        u_char  ip_tos;                 /* type of service */
        u_short ip_len;                 /* total length */
        u_short ip_id;                  /* identification */
        u_short ip_off;                 /* fragment offset field */
        #define IP_RF 0x8000            /* reserved fragment flag */
        #define IP_DF 0x4000            /* dont fragment flag */
        #define IP_MF 0x2000            /* more fragments flag */
        #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
        u_char  ip_ttl;                 /* time to live */
        u_char  ip_p;                   /* protocol */
        u_short ip_sum;                 /* checksum */
        struct  in_addr ip_src,ip_dst;  /* source and dest address */
		#define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
		#define IP_V(ip)                (((ip)->ip_vhl) >> 4)
};

/* ARP Header*/ 
struct arp { 
    u_int16_t htype;    /* Hardware Type           */ 
    u_int16_t ptype;    /* Protocol Type           */ 
    u_char hlen;        /* Hardware Address Length */ 
    u_char plen;        /* Protocol Address Length */ 
    u_int16_t oper;     /* Operation Code          */ 
    u_char sha[6];      /* Sender hardware address */ 
    u_char spa[4];      /* Sender IP address       */ 
    u_char tha[6];      /* Target hardware address */ 
    u_char tpa[4];      /* Target IP address       */ 
	#define ARP_REQUEST 1
	#define ARP_REPLY 2
}; 

/* TCP header */
typedef u_int tcp_seq;

struct tcp {
        u_short th_sport;               /* source port */
        u_short th_dport;               /* destination port */
        tcp_seq th_seq;                 /* sequence number */
        tcp_seq th_ack;                 /* acknowledgement number */
        u_char  th_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
        u_char  th_flags;
        #define TH_FIN  0x01
        #define TH_SYN  0x02
        #define TH_RST  0x04
        #define TH_PUSH 0x08
        #define TH_ACK  0x10
        #define TH_URG  0x20
        #define TH_ECE  0x40
        #define TH_CWR  0x80
        #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
        u_short th_win;                 /* window */
        u_short th_sum;                 /* checksum */
        u_short th_urp;                 /* urgent pointer */
};




發佈了38 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章