需注意的有一下几点:
1.pcap_next_ex返回的是从数据链路层开始的包,因此分析ip包应先去掉帧头
2.包由外而内数据链路层->ip层->tcp
3.结构体中位域的变量也有大小端的问题,因为我的机器是x86的,是小端,因此结构体定义没有考虑大端的情况
3.winpcap需要先complie然后才能filter,filter的规则为,我使用的是tcp and src host *.*.*.*,过滤源地址为*.*.*.*的tcp包
4.winpcap开发需要下载winpcap的开发包http://www.winpcap.org/devel.htm。然后在vs2010中的加入include和lib的目录,然后在链接器中加入lib目录下的.lib文件名,然后就能#include了
源代码有两个文件
贴一下:
tcp.h
-
#include <WinSock2.h>
-
/* 4字节的IP地址 */
-
typedef struct ip_address
-
{
-
u_char byte1;
-
u_char byte2;
-
u_char byte3;
-
u_char byte4;
-
} ip_address;
-
-
/* IPv4 首部 */
-
-
typedef struct header_tcp
-
{
-
u_short src_port;
-
u_short dst_port;
-
u_int seq;
-
u_int ack_seq;
-
u_short doff:4,hlen:4,fin:1,syn:1,rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1;
-
u_short window;
-
u_short check;
-
u_short urg_ptr;
-
}tcp_header;
-
typedef struct ip_header
-
{
-
u_char ver_ihl; // 版本 (4 bits) + 首部长度 (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;
main.cpp
-
#include <stdio.h>
-
#include <tchar.h>
-
#include <WinSock2.h>
-
#include <Windows.h>
-
-
#include <stdlib.h>
-
#include <iostream>
-
#include <string>
-
#define HAVE_REMOTE
-
#include <pcap.h>
-
#include "tcp_ip.h"
-
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;
-
char packet_filter[] = "tcp and (src host *.*.*.*)";//自己定义ip地址即可
-
struct bpf_program fcode;
-
-
-
/* 获取本机设备列表 */
-
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
-
{
-
fprintf(stderr,"Error in pcap_findalldevs: %sn", errbuf);
-
exit(1);
-
}
-
-
/* 打印列表 */
-
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;
-
}
-
-
printf("Enter the interface number (1-%d):",i);
-
scanf("%d", &inum);
-
-
if(inum < 1 || inum > i)
-
{
-
printf("nInterface number out of range.n");
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
return -1;
-
}
-
-
/* 跳转到选中的适配器 */
-
for(d=alldevs, i=0; i< inum-1 ; d=d->next, i++);
-
-
/* 打开设备 */
-
if ( (adhandle= pcap_open(d->name, // 设备名
-
65535, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
-
PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式
-
1000, // 读取超时时间
-
NULL, // 远程机器验证
-
errbuf // 错误缓冲池
-
) ) == NULL)
-
{
-
fprintf(stderr,"nUnable to open the adapter. %s is not supported by WinPcapn", d->name);
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
return -1;
-
}
-
-
printf("nlistening on %s...n", d->description);
-
-
-
/* 检查数据链路层,为了简单,我们只考虑以太网 */
-
if(pcap_datalink(adhandle) != DLT_EN10MB)
-
{
-
fprintf(stderr,"nThis program works only on Ethernet networks.n");
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
return -1;
-
}
-
printf("datalink:[%d]n", pcap_datalink(adhandle));
-
if(d->addresses != NULL)
-
/* 获得接口第一个地址的掩码 */
-
netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
-
else
-
/* 如果接口没有地址,那么我们假设一个C类的掩码 */
-
netmask=0xffffff;
-
-
-
//编译过滤器
-
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
-
{
-
fprintf(stderr,"nUnable to compile the packet filter. Check the syntax.n");
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
int x;
-
scanf("%d",&x);
-
return -1;
-
}
-
-
//设置过滤器
-
if (pcap_setfilter(adhandle, &fcode)<0)
-
{
-
fprintf(stderr,"nError setting the filter.n");
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
return -1;
-
}
-
-
printf("nlistening on %s...n", d->description);
-
-
/* 释放设备列表 */
-
pcap_freealldevs(alldevs);
-
-
-
-
/* 开始捕获 */
-
int ret;
-
struct pcap_pkthdr *header;
-
const u_char *pkt_data;
-
-
-
while ((ret = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0)
-
{
-
if(ret == 0)
-
{
-
/* 超时时间到 */
-
printf("time over!n");
-
continue;
-
}
-
char buffer[20000];
-
if (header->len > 0)
-
{
-
printf("len:[%d]n",header->len);
-
ip_header *ip =(ip_header *) (pkt_data +14);
-
printf("daddr:[%u.%u.%u.%u]n", ip->daddr.byte1,ip->daddr.byte2,ip->daddr.byte3,ip->daddr.byte4);
-
printf("saddr:[%u.%u.%u.%u]n", ip->saddr.byte1,ip->saddr.byte2,ip->saddr.byte3,ip->saddr.byte4);
-
tcp_header *tcp = (tcp_header *)((u_char*)ip + (ip->ver_ihl&0xf)*4);
-
char *data = (char *)tcp + (tcp->hlen)*4;
-
u_int datalen = ntohs(ip->tlen)-(ip->ver_ihl&0xf)*4-(tcp->hlen)*4;
-
-
-
memcpy(buffer, data, datalen);
-
buffer[datalen] = '';
-
printf("buffer:[%s]n", buffer+20);
-
}
-
}
-
return 0;
-
}
阅读(11461) | 评论(0) | 转发(0) |