Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7263452
  • 博文数量: 512
  • 博客积分: 12019
  • 博客等级: 上将
  • 技术积分: 6857
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-01 16:46
文章分类

全部博文(512)

文章存档

2024年(2)

2022年(2)

2021年(6)

2020年(59)

2019年(4)

2018年(10)

2017年(5)

2016年(2)

2015年(4)

2014年(4)

2013年(16)

2012年(47)

2011年(65)

2010年(46)

2009年(34)

2008年(52)

2007年(52)

2006年(80)

2005年(22)

分类: LINUX

2006-11-21 11:30:51

采用pcab包可以进一步学习TCP/IP协议.在windows下是winpcap函数包(注意需要同时安装驱动库。 可下载);linux下面是libpcap,一般安装linux时候直接就安装了(不要忘记,tcpdump就是用他实现的哦!)。而且利用改库我们就很方便的对socket数据包进行截取。下面是一个从文档里找到简单的例子。在vc下面编译通过。注意,为了顺利编译通过,还需到/devel.htm下下载编译库。

例子说明:
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;
}
阅读(4136) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~