采用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) |