诛仙422服务端 winpcap怎么 上传服务端

Windows下配置使用WinPcap - 推酷
Windows下配置使用WinPcap
windows: win7 x64
WinPcap版本:4.1.3
WinPcap开发包:4.1.2
目标:在VS2010中配置使用winpcap 获取目标计算机中安装的网卡列表
http://www.winpcap.org/
下载winpcap安装包 和 开发包
安装包安装完毕后,解压开发包到某个目录即可,开发包免安装。
&3、在VS2010中配置
配置头文件 和 库文件
项目属性--VC++目录--包含目录 / 库目录
获取本机 / 远程机器上网卡的列表和相关数据
/*******************************
函数成功返回 0
*******************************/
pcap_findalldevs_ex(
char *source,
//本机/远程机器/文件
struct pcap_rmtauth *auth,
//目标机器用户名 密码
pcap_if_t **alldevs,
//输出参数,详细信息
char *errbuf
//缓冲区 大小为PCAP_BUF_SIZE,函数失败时保存错误信息
pcap_findalldevs_ex函数指定本机时指定参数&rpcap://& 或 预定义宏PCAP_SRC_IF_STRING当指定远程机器时需要按照&rpcap://host:port&的格式,默认端口号为2002远程机器有密码时需要指定用户名和密码。
struct pcap_rmtauth
//#define RPCAP_RMTAUTH_NULL 0
用户名密码验证 #define RPCAP_RMTAUTH_PWD 1
// demo1.cpp : 定义控制台应用程序的入口点。
#include &stdafx.h&
#include &iostream&
#include &WinSock2.h&
#include &Windows.h&
//the macro HAVE_REMOTE must define before
HAVE_REMOTE
#define HAVE_REMOTE
#include &pcap.h&
#include &remote-ext.h&
#pragma comment(lib, &ws2_32.lib&)
#pragma comment(lib, &packet.lib&)
#pragma comment(lib, &wpcap.lib&)
using namespace
/************************************************************************/
/* platfor win7 x64
* version of winpcap: 4.1.3
* version of developping tool: 4.1.2
* notes: The local/remote machine must install the Winpcap
Start the server(go to the install path and double click rpcapd.exe).
You must look out that the DEFAULT PORT
If you use another port, the pcap_findalldevs_ex
function return -1
and the erro information in errbuf is
[Is the server properly installed on XXX.XXX.XXX.XXX?
connect() failed: 由于目标计算机积极拒绝,无法连接。
(code 10061) ]
/************************************************************************/
int _tmain(int argc, _TCHAR* argv[])
//char* pSource = &rpcap://&;
//localhost
char* pSource = &rpcap://XXX.XXX.XXX.XXX:2002&;
//remote PC
struct pcap_rmtauth stAuth = {0};
stAuth.type = RPCAP_RMTAUTH_PWD;
stAuth.username = &xxxxx&;
stAuth.password = &xxxxxxxxxxx&;
pcap_if_t* pPcapIft = NULL;
char chBuffer[PCAP_BUF_SIZE] = {0};
int nCount = 0;
if (0 == pcap_findalldevs_ex(pSource, &stAuth, &pPcapIft, chBuffer))
for (pcap_if_t* pcap = pPcapI pcap != NULL; pcap = pcap-&next)
cout && endl && &-----------
&& nCount ++
&& & -------------& &&
cout && pcap-&name
&& pcap-&description
&& pcap-&flags
cout && &-------- Output details below -----& &&
for (struct pcap_addr* pAddr = pcap-&
pAddr != NULL; pAddr = pAddr-&next)
struct sockaddr_in* psockAddr = (struct sockaddr_in*)(pAddr-&addr);
if (NULL != psockAddr)
cout && &IP is & && inet_ntoa(psockAddr-&sin_addr) &&
cout && &Port is & && ntohs(psockAddr-&sin_port) &&
cout && &Family is & && psockAddr-&sin_family &&
cout && &-------& &&
psockAddr = (struct sockaddr_in*)(pAddr-&dstaddr);
if (NULL != psockAddr)
cout && &Mask IP is & && inet_ntoa(psockAddr-&sin_addr) &&
cout && &Mask Port is & && ntohs(psockAddr-&sin_port) &&
cout && &Mask Family is & && psockAddr-&sin_family &&
cout && &-------& &&
psockAddr = (struct sockaddr_in*)(pAddr-&broadaddr);
if (NULL != psockAddr)
cout && &Broadcast IP is & && inet_ntoa(psockAddr-&sin_addr) &&
cout && &Broadcast Port is & && ntohs(psockAddr-&sin_port) &&
cout && &Broadcast Family is & && psockAddr-&sin_family &&
psockAddr = (struct sockaddr_in*)(pAddr-&dstaddr);
if (NULL != psockAddr)
cout && &P2P IP is & && inet_ntoa(psockAddr-&sin_addr) &&
cout && &P2P Port is & && ntohs(psockAddr-&sin_port) &&
cout && &P2P Family is & && psockAddr-&sin_family &&
cout && &---------------------------------------& && endl && endl &&
pcap_freealldevs(pPcapIft);
cerr && endl && &Last error is & && GetLastError() && endl
&& chBuffer &&
system(&pause&);
&5、运行结果
远程机器测试
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致使用WinPcap编程(4)&&把网络数据包存储到一个文件中 - 天地玄黄 - 博客园
posts - 128, comments - 22, trackbacks - 0, articles - 1
&&&&& 这里用到的数据结构是pcap_dumper_t,这也是一个相当于文件描述符的东西,我们在用的时候先指定pcap_dumper_t * &&&&& 使用两个函数来存储网络数据,一个是pcap_dump_open(),另一个是pcap_dump()。先用前一个函数打开一个文件,然后用后一个函数把网络数据写到这个文件中。最后用pcap_dump_close()这个函数把这个文件关闭。 &&&&& 函数原型如下: pcap_dumper_t * pcap_dump_open (pcap_t *p, const char *fname)
&&&&& 1、p是我们已经打开的网络设备,从这个设备接收数据包。
&&&&& 2、fname是我们要写入的文件名,随便起。
&&&&& return: 如果出错,会返回NULL。可以借此检查这个文件有没有打开。
&&&&& 文件打开之后,就可以向文件之中写数据了。数据也是一个包一个包的写进去的,还要用到pcap_loop()这个函数。只不过这里的user要指定为打开文件的描述符dumpfp。在使用packet_handler 这个函数指针的时候,参数中的user就是这个dumpfp。pcap_dump()的原型如下:
void pcap_dump (u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
&&&&& 1、这里的user就是文件描述符dumpfp,只不过要做一下类型转换。由于这个函数一般在pcap_loop()的函数指针所指向的packet_handler中使用,所以packet_handler中的user就是这里的user。
&&&&& 2、h是pkt_header。
&&&&& 3、sp这里要用pkt_data。具体参看下面的实例:
void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
printf("in packet handler\n");
pcap_dump(NULL, pkt_header, pkt_data);
&&&&& 附上一个源代码:
#define _CRT_SECURE_NO_WARNINGS
#include "pcap.h"
void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
int main()
pcap_t *cap_ins_
pcap_if_t *
pcap_if_t *d;
char source[PCAP_BUF_SIZE];
char errbuf[PCAP_ERRBUF_SIZE];
char packet_filter[] = "ip and udp"; // the filter
struct bpf_ // used in pcap_compile()
pcap_dumper_t *
/* set the source */
if (pcap_createsrcstr(source, PCAP_SRC_IFLOCAL, NULL, NULL, NULL, errbuf) == -1) {
printf("%s\n", errbuf);
printf("source: %s\n", source);
/* find all devices */
if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) {
printf("%s\n", errbuf);
/* choose one devices */
while (d != NULL) {
printf("%s, %s\n", d-&name, d-&description);
scanf("%d", &i);
while (--i)
printf("selected device: %s\n", d-&name);
/* open one device */
cap_ins_des = pcap_open(d-&name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
if (cap_ins_des == NULL) {
printf("%s\n", errbuf);
pcap_freealldevs(alldevs);
/* get the netmask, used at compiling the filter */
if (d-&addresses != NULL)
netmask = ((struct sockaddr_in *)(d-&addresses-&netmask))-&sin_addr.S_un.S_ /*@#$%^&*!*/
netmask = 0 /* 255.25.255.0 */
// netmask = 0;
/* compile the filter */
if (pcap_compile(cap_ins_des, &fcode, packet_filter, 1, netmask) & 0) {
printf("Error\n");
pcap_freealldevs(alldevs);
/* set the filter */
if (pcap_setfilter(cap_ins_des, &fcode) & 0) {
printf("Error\n");
pcap_freealldevs(alldevs);
/* open a file to dump data */
dumpfp = pcap_dump_open(cap_ins_des, "traffic.data");
if( dumpfp == NULL) {
printf("Error on opening output file\n");
pcap_freealldevs(alldevs);
/* start the capture */
pcap_loop(cap_ins_des, 30, packet_handler, (u_char *)dumpfp);
pcap_dump_close(dumpfp);
void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
printf("in packet handler\n");
pcap_dump(NULL, pkt_header, pkt_data);
&&&&& main()函数中下面的十来行是把网络数据包存到一个文件中的方法。网络安全技术(34)
&&&&&&&& 定义了TCP头部,IPv4地址,ip头结构体。此外还有一些和pcap相关的结构体和函数。
&&&&&&&& 结构体:,pcap_t,bpf_program
&&&&&&&& 函数:,pcap_freealldevs,pcap_open_live,,pcap_compile,pcap_setfilter,pcap_loop,packet_handler
&&&&&&&& pcap_findalldevs这个函数同pcap_findalldevs_ex,返回系统选中可用的接口。组建一个网络设备表,该表可被pcap_open_live()打开。(注意可能有些网络设备不能被pcap_open_live()通过调用pcap_findalldevs()打开,因为,例如进程不具有打开它们的特权;出现这种情况,这些设备将不会在列表中出现)alldevsp指向列表的第一项,列表的每一项都是一个pcap_if_t结构。
pcap_if_t*
pcap_if* next 如果不是为null,则指向列表的下一个元素;如果是空,则代表当前元素是最后一个元素。
char* name 指向字符串的指针 字符串用来向pcap_open_live()传递设备的名称
char* description 如果不为null,它指向的字符串是对设备的一个简单的描述。
pcap_addr* addresses 指向设备列表中第一个元素的地址;
u_int flags&&PCAP_IF_接口标志,当前只有PCAP_IDF_LOOPBACK,考察接口是不是一个自环接口。
pcap_freealldevs(pcap_if_t* alldevsp)
释放由pcap_findalldevs()返回的接口列表。
pcap_t* pcap_open_live(char* device, intsnaplen, int promisc,int to_ms, char* ebuf)
Deprecated: usethe&pcap_open()&instead.&打开一个物理接口进行捕获。
pcap_open_live()&用来获得一个观察网络数据包的包捕获描述符。Device是一个标识要打开的设备的字符串,on Linux systems with 2.2 or later kernels, a device argument of &any&or NULL can be used to capture packets from all interfaces. Snaplen定义要捕获的最大字节数。promisc定义是否将接口设置为混杂模式 (promiscuousmode.)。(注意:即使这个参数为false,接口也有可能因为其他原因而处于混杂模式下)
For now, this doesn't work on the &any& if anargument of &any& or NULL is supplied, the promisc flag is ignored.to_ms用毫秒定义读取超时。读取超时用以解决没有必要捕获数据包就开始读取,而是等待一段时间,有较多数据包到达,然后从操作系统内核一次读取多个数据包的问题。并不是所有平台支持读取超时。在不支持的平台上,这个参数被忽略。errbuf用来返回错误或者警告信息。当pcap_open_live()调用失败返回null时,errbuf被设定为错误信息。pcap_open_live()
调用成功时errbuf也可以被设置为警告信息。为得到这个信息,调用者应该在调用pcap_open_live()之前在errbuf中设定一个长度为0的字符串。调用后如果errbuf的长度不再为0,那么警告信息已经发生并可以显示出来。
int pcap_next_ex(pcap_t* p, structpcap_pkthdr** pkt_header, u_char** pkt_data)
Win32 Specific. Read a packet from aninterface or from an offline capture.
该函数用来检索下一个可用的数据包,&bypassing the callback method traditionally provided bylibpcap.
pcap_next_ex 用指向下一个捕获的数据包的数据头和数据的指针填充pkt_header和pkt_data参数。(see pcap_handler())
返回值可以是:
l&&&&&&&&1如果数据包被顺利读取
l&&&&&&&&0如果pcap_open_live()规定的读取超时已经过去。在这种情况下pkt_header和pkt_data指向的不是一个有用的数据包
l&&&&&&&&-1如果出现错误
l&&&&&&&&-2如果在离线捕获中遇到EOF。
timeval结构如下:
struct timeval{long tv_longtv_}
其中tv_sec为秒数,tv_usec微秒数。
返回链路层的类型,链路层的类型包括:
DLT_NULL: BSD回路封装;链路层协议头是一个4字节的域,以主机字节顺序(host byte order),包含一个从socket.h来的PF_value。主机字节顺序(host byte order)是捕获数据包的机器的字节顺序,而PF_value是捕获数据包的机器的OS。如果一个读取一个文件,字节顺序和PF_value不一定是抓取文件的那些机器。
DLT_EN10MB: 以太网(10Mb, 100Mb,1000Mb, 或者更高)。
DLT_IEEE802: IEEE802.5令牌环网。
DLT_ARCNET:ARCNET。
DLT_SLIP:SLIP。
DLT_PPP:PPP;如果第一个字节是0xff或0x03,它是类HDLC帧上的PPP。
DLT_FDDI:FDDI
DLT_ATM_RFC1483:RFC1483LLC/SNAPATM;数据包以IEEE802.2 LLC头开始。
DLT_RAW:原始IP(raw IP);数据包以IP头开始。
DLT_PPP_SERIAL:按照RFC1662,基于类HDLC帧的PPP,或者按照RFC.1,基于HDLC帧的Cisco PPP;前者的第一个字节是0xFF,后者的第一个字节是0x0F或0x8F。
DLT_PPP_ETHER:按照RFC2516,PPPoE;数据包以PPPoE头开始。
DLT_C_HDLC:按照RFC.1,基于HDLC帧的Cisco PPP。
DLT_IEEE802_11:IEEE 802.11无线局域网。
DLT_FRELAY:帧中继(Frame Relay)。
DLT_LOOP:OpenBSD回路封装。
DLT_LINUX_SLL:抓包封装。
DLT_LTALK:苹果的LocalTalk,数据包以AppleTalkLLAP头开始。
DLT_PFLOG:OpenBSD pflog。
DLT_PRISM_HEADER:后接802.11头的棱镜监视器模式(Prismmonitor mode)信息。
DLT_IP_OVER_FC:RFC2625IP-over-Fiber 频道,以RFC2625中定义的Network_Header开始。
DLT_SUNATM:SunATM设备。
DLT_IEEE802_11_RADIO:后接802.11头的链路层信息。
DLT_ARCNET_LINUX:没有异常帧的ARCNET。
DLT_LINUX_IRDA:Linux-IrDA数据包,DLT_LINUX_SLL头后接IrLAP头。
intpcap_compile(pcap_t*&&&&&&&&&&&&&&&&&&&&p,
struct bpf_program*&&&&fp,
char*&&&&&&&&&&&&&&&&&&&&&&&&&&str,
int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&optimize,
bpf_u_int32&&&&&&&&&&&&&&&&netmask)
编译一个数据包过滤器,将一个能被核心态(kernel-level)过滤器引擎解释的程序中的高层过滤表达式(filtering expression)进行转化。pcap_compile()被用来将字符串str编译进过滤器程序(fp),程序(fp)是一个指向bpf_program结构体并被pcap_compile()赋值的指针。optimize控制是否对目标代码(resulting code)的性能进行优化。Netmask表明IPv4掩码,它仅在检查过滤器程序中的IPv4广播地址的时候被使用。如果网络掩码对于程序是不可知的或者数据包是在Linux的”任何(any)”伪接口上被捕获的,则赋值0;IPv4广播地址的将不被正确进行,但过滤器程序中的其他所有的测试都不会有问题。返回-1表示发生了错误,此时,pcap_geterr()将被用来显示错误信息。
pcap_setfilter
intpcap_setfilter(pcap_t*&&&&&&&&&p,
struct bpf_program* fp)
&&&&把一个过滤器同一次抓包关联起来。pcap_setfilter被用来指定一个过滤器程序。fp是一个指向bpf_program结构体的指针,通常是pcap_compile()执行的结果。当失败时返回-1,此时,pcap_geterr()被用来显示错误信息;返回0表示成功。
int pcap_loop(pcap_t * p,int cnt, pcap_handler callback, uchar *user);
捕获数据包,不会响应()函数设置的超时时间
p 是由pcap_open_live()返回的所打开的网卡的;cnt用于设置所捕获数据包的个数;pcap_handler是与void packet_handler()使用的一个参数,即的名称;user值一般为NULL
pcap_loop原型是pcap_loop(pcap_t *p,int cnt,pcap_handler callback,u_char *user)
其中第一个参数是winpcap的句柄,第二个是指定捕获的数据包个数,如果为-1则无限循环捕获。第四个参数user是留给用户使用的。
第三个是回调函数。
可进行包处理,与pcap_loop等回调函数联合使用进行抓包  
u_char *param:数据包存储的文件指针   
struct pcap_pkthdr * header: 并非是数据包的指针,只是与数据包捕获驱动有关的一个header ,是堆文件包的结构体首部指针。可以得到时间值,数据包长度。  
const_char * pkt_data:指向数据包内容的指针,包括了协议头,可以经过计算获得IP数据包头部的位置, UDP首部的位置。 
//捕获网络数据包的C++程序
//可以获得数据包长度、通过以太网类型确定上层协议、源以太网地址和目的以太网地址!
#include&tchar.h&
#include&stdio.h&
#include&pcap.h&
#pragmacomment(lib,&wpcap.lib&)&&
#pragmacomment(lib,&packet.lib&)&&
#pragmacomment(lib,&ws2_32.lib&)&&
typedefstructip_address{
&&& u_char byte1;
&&& u_char byte2;
&&& u_char byte3;
&&& u_char byte4;
}ip_address;
typedefstructip_header{
&&& u_char&ver_&&&&&&&
// 版本 (4 bits) +
首部长度 (4 bits)
&&& u_char&&&&&&&&&&&&
// 服务类型(Type of service)
&&& u_short&&&&&&&&&&//
总长(Total length)
&&& u_short
//标识(Identification)
&&& u_short flags_&&&&&&//
标志位(Flags) (3 bits) +
段偏移量(Fragment offset) (13bits)
&&& u_char&&&&&&&&&&&&
// 存活时间(Time to live)
&&& u_char&&&&&&&&&&
// 协议(Protocol)
&&& u_short&&&&&&&&&&&//
首部校验和(Header checksum)
&&& ip_address&&&&&&
// 源地址(Source address)
&&& ip_address&&&&&&
// 目的地址(Destination address)
&&& u_int&&op_&&&&&&&&
// 选项与填充(Option + Padding)
}ip_header;
typedefstructtcp_header{
&&& u_short&&&&&&&&&//
源端口(Source port)
&&& u_short&&&&&&&&&//
目的端口(Destination port)
&&& u_int seqN&&&&&&&&&&&
//tcp请求序列号
&&& u_int ackN&&&&&&&&&&&
//ack应答序列号
&&& u_char hL&&
//tcp头长度
&&& u_char&&//标志字段
&&& u_short winS&//窗口大小
&&& u_short checkS&//校验和
}tcp_header;
voidpacket_handler(u_char *param,
conststructpcap_pkthdr *header,
constu_char*pkt_data);
int_tmain(intargc,
&&& pcap_if_t *
&&& pcap_if_t *d;
&&& int i=0;
&&& pcap_t *
&&& char errbuf[PCAP_ERRBUF_SIZE];
&&& char packet_filter[] =
&tcp and ip&;
&&& structbpf_program
&&& if (pcap_findalldevs(&alldevs, errbuf) == -1)
&&&&&&& fprintf(stderr,&Error in pcap_findalldevs:%s\n&,
&&&&&&& exit(1);
&&& for(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_s(&%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_live(d-&name,&&&&&&&&&
&&&&&&& 65536,&&&&&&&&&&&
//65535保证能捕获到不同数据链路层上的每个数据包的全部内容
&&&&&&& TRUE,&&&
// 混杂模式
&&&&&&& 1000,&&&&&&&&&&&&
//读取超时时间&
&&&&&&& errbuf&&&&&&&&&&&
//错误缓冲池
&&&&&&& )) == NULL)
&&&&&&& fprintf(stderr,&\nUnable to open theadapter.
%s is not supported by WinPcap\n&,d-&name);
&&&&&&& pcap_freealldevs(alldevs);
&&&&&&& return -1;
&&& if(pcap_datalink(adhandle) !=
DLT_EN10MB)
&&&&&&& fprintf(stderr,&\nThis program works onlyon
Ethernet networks.\n&);
&&&&&&& pcap_freealldevs(alldevs);
&&&&&&& return -1;
&&& if(d-&addresses !=
&&&&&&& netmask=((structsockaddr_in *)(d-&addresses-&netmask))-&sin_addr.S_un.S_
&&&&&&& netmask=0
&&& //编译过滤器
&&& if (pcap_compile(adhandle, &fcode,packet_filter, 1, netmask) &0 )
&&&&&&& fprintf(stderr,&\nUnable to compile thepacket
filter. Check the syntax.\n&);
&&&&&&& pcap_freealldevs(alldevs);
&&&&&&& return -1;
&&& //设置过滤器
&&& if (pcap_setfilter(adhandle, &fcode)&0)
&&&&&&& fprintf(stderr,&\nError setting thefilter.\n&);
&&&&&&& pcap_freealldevs(alldevs);
&&&&&&& return -1;
&&& printf(&\nlistening on %s...\n&,d-&description);
&&& pcap_freealldevs(alldevs);
&&& pcap_loop(adhandle,0, packet_handler,
&&& return 0;
voidpacket_handler(u_char *param,
conststructpcap_pkthdr *header,
constu_char *pkt_data)
&&& structtm*
&&& char timestr[16];
&&& ip_header *
&&& tcp_header *
&&& u_int ip_
&&& u_short sport,
&&& time_t local_tv_
&&& local_tv_sec= header-&ts.tv_
&&& ltime=localtime(&local_tv_sec);
&&& strftime(timestr, sizeof timestr,
&%H:%M:%S&, ltime);
&&& printf(&%s.%.6d len:%d &, timestr,
header-&ts.tv_usec,
header-&len);
&&& ih= (ip_header*) (pkt_data+
&&&&&&& 14);//以太网头部长度
&&& ip_len= (ih-&ver_ihl & 0xf) * 4;
&&& th= (tcp_header*) ((u_char*)ih
+ ip_len);
&&& sport= ntohs( th-&sport );
&&& dport= ntohs( th-&dport );
&&& printf(&%d.%d.%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,
&&&&&&& dport);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:334117次
积分:14397
积分:14397
排名:第612名
原创:1102篇
转载:111篇
译文:14篇
评论:45条
(54)(16)(5)(64)(61)(36)(29)(117)(152)(24)(135)(115)(129)(23)(95)(29)(34)(23)(14)(23)(8)(11)(7)(5)(30)(8)(原创)WinpCap的详解(三) - yingfang18 - 博客园
随笔 - 21, 文章 - 0, 评论 - 27, 引用 - 0
  接着WinpCap详解(二),这篇博客主要来讨论一下,堆文件的处理以及简单发送数据包。
1、处理脱机堆文件
  我们将学习如何处理捕获到文件中的数据包。 WinPcap提供了很多函数来将网络数据流保存到文件并读取它们 -- 本讲将教你如何使用这些函数。我们还将看到如何使用WinPcap内核堆特性来获取一个高性能的堆。
  堆文件的格式是libpcap的一种。这种格式中,包含了被捕捉到的包的二进制数据,并且,这种格式是许多网络工具所使用的一种标准,这些工具包括WinDump,Etheral和Snort。
 保存数据包到堆文件
  首先,让我们看一下如何将一个数据包写成libpcap的格式。
  接下来的例子讲从一个选定的接口捕获数据包,并且将它们保存到用户指定的文件中。 
  这里pcap_dump_t和pcap_dump一样的东西,表示的是libpcap存储文件的描述符,对用户来说也是不透明的。
  这里的pcap_findalldevs_ex()函数是pcap_findalldevs()的扩展。这里我列出他的英文解释吧,翻译起来还不是很好,看英文比较容易了。
  This function is a superset of the old 'pcap_findalldevs()', which is obsolete, and which allows listing only the devices present on the local machine. Vice versa, pcap_findalldevs_ex() allows listing the devices present on a remote machine as well. Additionally, it can list all the pcap files available into a given folder. Moreover, pcap_findalldevs_ex() is platform independent, since it relies on the standard pcap_findalldevs() to get addresses on the local machine.
  pcap_dump_open(pcap_t* p,const char* name)打开一个堆文件,第二个参数是文件的名字,第一个参数是已经打开的适配器描述符。
#include "pcap.h"
/* 回调函数原型 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
main(int argc, char **argv)
pcap_if_t *
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_dumper_t *
/* 检查程序输入参数 */
if(argc != 2)
printf("usage: %s filename", argv[0]);
return -1;
/* 获取本机设备列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
/* 打印列表 */
for(d= d=d-&next)
printf("%d. %s", ++i, d-&name);
if (d-&description)
printf(" (%s)\n", d-&description);
printf(" (No description available)\n");
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保证能捕获到不同数据链路层上的每个数据包的全部内容
PCAP_OPENFLAG_PROMISCUOUS,
// 混杂模式
// 读取超时时间
// 远程机器验证
// 错误缓冲池
) ) == NULL)
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d-&name);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return -1;
/* 打开堆文件 */
dumpfile = pcap_dump_open(adhandle, argv[1]);
if(dumpfile==NULL)
fprintf(stderr,"\nError opening output file\n");
return -1;
printf("\nlistening on %s... Press Ctrl+C to stop...\n", d-&description);
/* 释放设备列表 */
pcap_freealldevs(alldevs);
/* 开始捕获 */
pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);
/* 回调函数,用来处理数据包 */
void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data)
/* 保存数据包到堆文件 */
pcap_dump(dumpfile, header, pkt_data);
 从堆文件中读取数据包
  既然我们有了可用的堆文件,那我们就能读取它的内容了。 以下代码将打开一个WinPcap/libpcap的堆文件,并显示文件中每一个包的信息。文件通过 pcap_open_offline() 打开,然后,我们通常使用 pcap_loop() 来有序获取数据包。你可以看到,从脱机文件中读取数据包和从物理接口中接收它们是很相似的。
  这个例子还会介绍另一个函数:pcap_createsrcsrc()。这个函数用于创建一个源字符串,这个源字符串以一个标志开头,这个标志会告诉WinPcap这个源的类型。比如,使用"rpcap://"标志来打开一个适配器,使用"file://"来打开一个文件。如果 pcap_findalldevs_ex() 已经被使用,那么这部是不需要的,因为其返回值已经包含了这些字符串。然而,在这个例子中,我们需要它。因为文件的名字来自于用户的输入。
2、发送数据包
  尽管从 WinPcap 的名字上看,这个库的目标应该是数据捕捉(Packet Capture),然而,它也提供了针对很多其它有用的特性。在其中,我们可以找到一组很完整的用于发送数据包的函数。
  请注意:原始的libpcap库是不支持发送数据包的,因此,这里展示的函数都属于是WinPcap的扩展,并且它们不能运行于Unix平台下。
  使用 pcap_sendpacket() 发送单个数据包
  下面的代码展示了发送一个数据包的最简单的方式。打开适配器以后,调用 pcap_sendpacket() 来发送手工制作的数据包。 pcap_sendpacket() 的参数有一个要包涵发送数据的缓冲区,缓冲的长度,以及用来发送数据的适配器。注意,缓冲数据将直接发送到网络,而不会进行任何加工和处理。这就意味着应用程序需要创建一个正确的协议首部,来使这个数据包更有意义。
#include &stdlib.h&
#include &stdio.h&
#include &pcap.h&
void main(int argc, char **argv)
char errbuf[PCAP_ERRBUF_SIZE];
u_char packet[100];
/* 检查命令行参数的合法性 */
if (argc != 2)
printf("usage: %s interface (e.g. 'rpcap://eth0')", argv[0]);
/* 打开输出设备 */
if ( (fp= pcap_open(argv[1],
// 要捕获的部分 (只捕获前100个字节)
PCAP_OPENFLAG_PROMISCUOUS,
// 混杂模式
// 读超时时间
// 远程机器验证
// 错误缓冲
) ) == NULL)
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
/* 假设在以太网上,设置MAC的目的地址为 1:1:1:1:1:1 */
packet[0]=1;
packet[1]=1;
packet[2]=1;
packet[3]=1;
packet[4]=1;
packet[5]=1;
/* 设置MAC源地址为 2:2:2:2:2:2 */
packet[6]=2;
packet[7]=2;
packet[8]=2;
packet[9]=2;
packet[10]=2;
packet[11]=2;
/* 填充剩下的内容 */
for(i=12;i&100;i++)
packet[i]=i%256;
/* 发送数据包 */
if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)
fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));
  这里面只是简单的数据发送,还有更复杂的队列发送,由于现在不需要用到这一块,所以就不看这一部分了,因为我只需要发送简单的命令,不需要大量的数据发送,这里就不再讲下去啦,如果想更深入的了解WinpCap的功能,推荐一个好的网站,,这个网站里面有很多关于WinpCap的东西,可能里面有很多更新的东西,还值得大家以后共同学习,本人就学习这么多啦!

我要回帖

更多关于 诛仙422服务端 的文章

 

随机推荐