close
采用pcab包可以進一步學習TCP/IP協議.在windows下是winpcap函數包(註意需要同時安裝驅動庫。http://www.winpcap.org 可下載);linux下面是libpcap,一般安裝linux時候直接就安裝了(不要忘記,tcpdump就是用他實現的哦!)。而且利用改庫我們就很方便的對socket數據包進行截取。下面是一個從文檔裏找到簡單的例子。在vc下面編譯通過。註意,為了順利編譯通過,還需到http://www.winpcap.org/devel.htm下下載WinPcap 3.1編譯庫。

例子說明:
1、本例子是截獲tcp數據包,並打印出地址和數據長度,同時取得http協議種使用的cookie。
2、本例子在linux沒有去測試,但是兩個庫得函數形式一致,而且例子基本上都是c形式代碼,相信移植也很
   簡單。

#include "stdafx.h"

#include
#include

/* 4 bytes IP address */
typedef struct ip_address
{
 u_char byte1;
 u_char byte2;
 u_char byte3;
 u_char byte4;
}ip_address;

/* IPv4 header */
typedef struct ip_header
{
 u_char ver_ihl;  /* Version (4 bits) + Internet header length (4 bits)*/
 u_char tos;      /* Type of service */
 u_short tlen;    /* Total length */
 u_short identification; /* Identification */
 u_short flags_fo;       /* Flags (3 bits) + Fragment offset (13 bits)*/
 u_char ttl;      /* Time to live */
 u_char proto;    /* Protocol */
 u_short crc;     /* Header checksum */
 ip_address saddr;/* Source address */
 ip_address daddr;/* Destination address */
 u_int op_pad;    /* Option + Padding */
}ip_header;

/* UDP header */
typedef struct udp_header
{
 u_short sport;   /* Source port */
 u_short dport;   /* Destination port */
 u_short len;     /* Datagram length */
 u_short crc;     /* Checksum */
}udp_header;



/* TCP header */
typedef struct tcp_header
{
 u_short nSrcPort;
 u_short nDesPort;
 u_int   SeqNum;
 u_int   AckSeqNum;
 u_char   headLen;

}tcp_header;

/*聲明回調函數 Prototype of the pachet handler */
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data);


int FindCookie(const char * pBuf,char * pCookie);

int main()
{
    pcap_if_t* alldevs;
    pcap_if_t* d;
    int inum;
    int i = 0;
    pcap_t* adhandle;
    char errbuf[PCAP_ERRBUF_SIZE];
    u_int netmask;
    //註意該處設置過濾條件,形式和tcpdump一致
    char packet_filter[] = "tcp and host 192.168.99.199 and port 80";
    struct bpf_program fcode;

    /* Retrieve the device list */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }

    /* Print all net adapter in the list*/
    for (d = alldevs; d; d = d->next)
    {
        printf("%d. %s", ++ i, d->name);
        if (d->description)
        {
            printf(" (%s)\n", d->description);
        }
        else
        {
            printf(" (No description available)\n");
        }
    }

    if (i == 0)
    {
        printf("\nNo interfaces found! Make sure Winpcap is installed.\n");
        return -1;
    }
    //select one of adapter for snatch
    printf("Enter the interface number (1 - %d):", i);
    scanf("%d", &inum);
    if (inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        /* Free the device list */
        pcap_freealldevs(alldevs);
        return -1;
    }

    /* Jump to the selected adapter */
    // for (d = alldevs; d; d = d->next);
    d = alldevs;

    /* Open the adapter */
    if ((adhandle = pcap_open(d->name,  /*name of the device */
        65536,      /* portion of the packet to capture */
        /* 65536 grants that the whole packet will be captured on all the MACs */
        PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
        1000,       /* read timeout */
        NULL,       /* remote authentication */
        errbuf      /* error buffer */
        )) == NULL)
    {
        fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n");
        /* Free the devices list */
        pcap_freealldevs(alldevs);
        return -1;
    }

    /* Check the link layer. We support only Ethernet for simplicity */
    if (pcap_datalink(adhandle) != DLT_EN10MB)
    {
        fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
        /* Free the devices list */
        pcap_freealldevs(alldevs);
        return -1;
    }

    if (d->addresses != NULL)
    {
        /* Retrieve the mask of the first address of the interface */
        netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
    }
    else
    {
        /* If the interface is without addresses we suppose to be in a C class network */
        netmask = 0xffffffff;
    }

    /* complie the filter */
    if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
    {
        fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
        /* Free the devices list */
        pcap_freealldevs(alldevs);
        return -1;
    }
    /* set the filter */
    if (pcap_setfilter(adhandle, &fcode) < 0)
    {
        fprintf(stderr, "\nError setting the filter.\n");
        /* Free the devices list */
        pcap_freealldevs(alldevs);
        return -1;
    }

    printf("\nlistening on %s ...\n", d->description);

    /* At this point,we don’t need any more the device list. Free it */
    pcap_freealldevs(alldevs);

    /* Start the capture */
    pcap_loop(adhandle, 0, packet_handler, NULL);

    return 1;
}

/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data)
{
    struct tm* ltime;
    char timestr[16];
    ip_header* ih;
    udp_header* uh;
    u_int ip_len;
    u_short sport, dport;
    tcp_header *tcpHead=NULL;
    /* convert the timestamp to readable format */
    ltime = localtime(&header->ts.tv_sec);
    strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);

    /* print timestamp and length of the packet */
    printf("%s.%.6d len: %d\n ", timestr, header->ts.tv_usec, header->len);

    /* retrieve the position of the ip header */
    ih = (ip_header*)(pkt_data + 14);  /* length of ethernet header */

    /* retrieve the position of the udp header */
    ip_len = (ih->ver_ihl & 0xf) * 4;
    tcpHead = (tcp_header*)((u_char*)ih + ip_len);
    int tcpHeadLen = (4*(tcpHead->headLen)>>4);

    //取得應用數據(http數據),目的分析cookie
    char *pData =  (char*)((u_char*)ih + ip_len+tcpHeadLen);
    char szCookie[1024];
    memset(szCookie,0,sizeof(szCookie));
    int nRet = FindCookie(pData,szCookie);
    if(nRet ==0 )
    {
        printf("Cookie=%s",szCookie);
        FILE *fp = fopen("d:\\out.txt","aw");
        fprintf(fp,"%s",szCookie);
        fclose(fp);
        //exit(1);
    }

    /* print ip addresse*/
    printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
    ih->saddr.byte1,
    ih->saddr.byte2,
    ih->saddr.byte3,
    ih->saddr.byte4,
    /*sport,*/
    ih->daddr.byte1,
    ih->daddr.byte2,
    ih->daddr.byte3,
    ih->daddr.byte4
    );

}

int FindCookie(const char * pBuf,char * pCookie)
{
    char *p =  strstr(pBuf,"Cookie");
    if(p==NULL)
        return -1;

    char *pEnd =  strstr(p,"\r\n");
    if(p==NULL)
        return -1;
    int Len =pEnd-p;
    if(Len>1024)
        Len =1024;
    memmove(pCookie,p,Len);

    return 0;
}
arrow
arrow
    文章標籤
    Windows 編程 開發 網絡
    全站熱搜

    成功运行 發表在 痞客邦 留言(0) 人氣()