利用libpcap分析網絡上的數據包(入門級)


本文可任意轉載,但請保留作者及出處
作者:rainfish
出處:http://blog.csdn.net/bat603/
經過幾天的突擊,終於明白了怎樣在局域網內抓包,這可是我多年來的夢想。首先說說我的學習過程,一開始從網上搜索了關於sniffer大量資料,大致學會了,可是仔細分析結果發現,都是本機上的數據包,而不是整個局域網的。於是又查資料,在 linuxsir上有高人指點,說,現在局域網內都是交換機聯接,而不是以前的Hub所以,如果要抓整個局域網的數據包,必須用libpcap,於是又查了許多關於Libpcap的資料,經過一天的努力,總算稍微有點眉目了。總結手里的資料,它們都在講怎樣用libpcap抓包,而沒有講怎樣去分析包,所以在下就寫了一個小小的例子,去分析數據包里的具體信息,如果有不正確的地方,敬請指正。
關於libpcap的使用方法,請參考我收集的的資料
http://blog.csdn.net/bat603/archive/2006/09/04/1175729.aspx
http://blog.csdn.net/bat603/archive/2006/09/04/1176251.aspx
下邊這個比較深奧
http://blog.csdn.net/bat603/archive/2006/09/04/1175271.aspx

源代碼及解釋
/**************************************************************
********************rainfish**********************************
***************http://blog.csdn.net/bat603/**********************
**********本文可任意轉載,但請保留作者及出處*****************/

//該程序使用方法:./exe_your_file  numpacket
#include <stdio.h>
#include <pcap.h>
/* if this gives you an error try pcap/pcap.h 里面有相應的數據結構一般在/usr/include/中*/

#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>//注意使用的ip、tcp數據結構,至於它們和 <netinet/ip.h | tcp.h>的區別,我也弄不清楚。

/*回調函數,int pcap_loop(pcap_t *p, int cnt,
          pcap_handler callback, u_char *user)調用的
這里需要說明的是,關於參數 pkthdr、packet的說明,好多資料都沒有進行解釋,在這里我只能嘗試的去解釋
當執行pcap_loop,會自動調用回調函數,pcap_t *p是調用者傳遞的,參看下面例子,而pkthdr(libpcap 自定義數據包頭部),packet(捕獲的書據包)就會相應得到,而不用用戶操作。下面的例子也能證明這一點。我實在不敢確定,因為沒有找到相應的文檔
*/
void my_callback(u_char *userless, const struct pcap_pkthdr *pkthdr, 
                    const u_char *packet)
{
    struct in_addr addr;
    struct iphdr *ipptr;
    struct tcphdr *tcpptr;//太次片,,ip,tcp數據結構
    char *data;
        
    pcap_t *descr = (pcap_t*)userless;//捕獲網絡數據包的數據包捕獲描述字
    //const u_char *packet;
    struct pcap_pkthdr hdr = *pkthdr;//(libpcap 自定義數據包頭部),
    struct ether_header *eptr;//以太網字頭
    u_char *ptr;
    int i;
 
    if (packet == NULL)//packet里面有內容,可以證明上面的猜想,
    {
        printf ("Didn't grab packet!/n");
        exit (1);
    }
    printf ("/n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/n");
    printf ("Grabbed packet of length %d/n", hdr.len);
    printf ("Received at : %s/n", ctime((const time_t*)&hdr.ts.tv_sec));
    printf ("Ethernet address length is %d/n", ETHER_HDR_LEN);
    
    eptr = (struct ether_header*)packet;//得到以太網字頭
    
    if (ntohs(eptr->ether_type) == ETHERTYPE_IP)
    {
        printf ("Ethernet type hex:%x dec:%d is an IP packet/n",
                    ntohs(eptr->ether_type), ntohs(eptr->ether_type));
    }
    else 
    {
        if (ntohs(eptr->ether_type) == ETHERTYPE_ARP)
        {
            printf ("Ethernet type hex:%x dec:%d is an ARP packet/n",
                        ntohs(eptr->ether_type), ntohs(eptr->ether_type));
        }
        else
        {
            printf ("Ethernet type %x not IP/n", ntohs(eptr->ether_type));
            exit (1);
        }
    }
        
    ptr = eptr->ether_dhost;
    i = ETHER_ADDR_LEN;
    printf ("i=%d/n", i);
    printf ("Destination Address: ");
    do
    {
        printf ("%s%x", (i == ETHER_ADDR_LEN)?"":":", *ptr++);
    }while(--i>0);
    printf ("/n");
    //printf ("%x/n",ptr);
    
    ptr = eptr->ether_shost;
    i = ETHER_ADDR_LEN;
    printf ("Source Address: ");
    do
    {
        printf ("%s%x", (i == ETHER_ADDR_LEN)?"":":", *ptr++);
    }while(--i>0);
    printf ("/n");
    printf ("Now decoding the IP packet./n");
    ipptr = (struct iphdr*)    (packet+sizeof(struct ether_header));//得到ip包頭
    
    printf ("the IP packets total_length is :%d/n", ipptr->tot_len);
    printf ("the IP protocol is %d/n", ipptr->protocol);
    addr.s_addr = ipptr->daddr;
    printf ("Destination IP: %s/n", inet_ntoa(addr));    
    addr.s_addr = ipptr->saddr;
    printf ("Source IP: %s/n", inet_ntoa(addr));
    
    printf ("Now decoding the TCP packet./n");
    tcpptr = (struct iphdr*)(packet+sizeof(struct ether_header)
                                    +sizeof(struct iphdr));//得到tcp包頭
    printf ("Destination port : %d/n", tcpptr->dest);
    printf ("Source port : %d/n", tcpptr->source);
    printf ("the seq of packet is %d/n", tcpptr->seq);
//以上關於ip、tcp的結構信息請查詢/usr/include/linux/ip.h | tcp.h
    
    data = (char*)(packet+sizeof(struct ether_header)+sizeof(struct iphdr)
                                    +sizeof(struct tcphdr));//得到數據包里內容,不過一般為亂碼。
    
    printf ("the content of packets is /n%s/n",data);
}
int main(int argc, char **argv)
{
    int i;
    char *dev;
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *descr;
    const u_char *packet;
    struct pcap_pkthdr hdr;
    struct ether_header *eptr;
    
    if (argc != 2)
    {
        fprintf (stdout, "Usage: %s numpackets/n", argv[0]);
        return 0;
    }
    
    dev = pcap_lookupdev (errbuf);
    if (dev == NULL)
    {
        printf ("%s/n", errbuf);
        exit (1);
    }
    
    descr = pcap_open_live (dev, BUFSIZ, 1, -1, errbuf);
    //第三個參數,1為混雜模式;0為非混雜模式
    //BUFSIZ同PCAP_ERRBUF_SIZE一樣,均為庫文件已經定義好的,不推薦使用
    if (descr == NULL)
    {
        printf ("pcap_open_live(): %s/n", errbuf);
        exit (1);
    }
    pcap_loop (descr, atoi(argv[1]), my_callback, NULL);//調用回調函數
    
 
        
    printf("Hello world/n");
    return (0);
}
關於過濾機制,以后再寫


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM