本博客将叙述几个关键的winpcap api
研习完本博客,可以最终实现抓包/发包操作
环境描述:
系统: windows 8.1
编译器: visaul stiduo 2015
pcap 执行版本: 4.1.3
pcap 开发包版本: 4.1.2
环境配置:
传送门:winpcap在visual stiduo 2015上进行配置
_
findalldevs_
ex主要用于获得所有本地的网络接口
char *source: 关于lcoal/remote的设定,如果是查找本地的网路设备,填写PCAP_SRC_IF_STRING
struct pcap_rmtauth *auth: 权限设置,一般填NULL
pcap_
if_
t **alldevs: 保存扫描结果。struct pcap
if
t
保存了设备的信息/描述
0 : 成功执行
-1 : 执行失败
pcap_if_t * allDevs;
pcap_if_t * dev;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allDevs, errbuf) > 0) {
printf("pcap_findallDevs_ex failed\n");
}
for (dev = allDevs; dev->next != NULL; dev = dev->next) {
printf("----------------------------\n");
printf("name %s\n", dev->name);
printf("description :%s\n", dev->description);
}
_
t* pcap_
open主要用于对指定的网络设备进行抓包/发包
const char *source: 填充pcap_
if_
t -> name, 用于指定网络设备
int snaplen: 最大接受数据包的大小
int flags: 网络设备的监听模式,一般设置为混杂模式PCAP_OPENFLAG_PROMISCUOUS
,即只要经过该网络设备的数据包都会被捕获
int read_timeout: 抓到包之后,并不是立即返回,而是再允许其他的包进入。此参数可能存在系统不支持
struct pcap_
rmtauth * auth: 权限,一般传入NULL
char * errbuf: 如果函数出错,存储错误信息
pcap_t * : 执行成功
NULL : 执行失败,错误信息填充在errbuf
抓包(抓一次,抓一个)
_
t * p: 指定抓包的网络设备,即pcap_
open的返回值struct pcap_
pkthdr ** pkt_
header: 抓到包的描述,由winpcap自动生成
const u_char ** pkt_
data: 存储完整的包数据
1: 成功执行
0 : 超时,此时pkt_
header,pkt_
data所指向的包并不是有效的
-1 : 出现错误
-2 : 读取离线包时,出现了EOF结束符
发包
pcap_
t * p: 指定网络设备,使用此网络设备进行发包
u_char * buf: 数据包
int size: 数据包的大小
0 : 发送成功
-1 : 发送失败
#include
#include
#include
#define HAVE_REMOTE
int main() {
pcap_if_t * allDevs;
pcap_if_t * dev;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allDevs, errbuf) > 0) {
printf("pcap_findallDevs_ex failed\n");
}
int i = 0;
//找到连接到internet的网络设备,根据自己电脑的环境自行更改i的终值
/*windows下,要使用descroption近似为
Network adapter 'Realtek PCIe GBE Family Controller' on local host
的网络设备 */
for (dev = allDevs, i = 0; i< 4; dev = dev->next, i++);
pcap_t * handler;
if (NULL == (handler = pcap_open(dev->name, 65535, PCAP_OPENFLAG_PROMISCUOUS, 3000, NULL, errbuf))) {
//设置接受的包大小为65535,即可以接受所有大小的包
printf("err in pcap_open : %s", errbuf);
}
pcap_pkthdr *pkt_header;
const u_char *pkt_data;
for (int j = 0; j < 5; j++) {
printf("%d --------\n", j);
if (1 == pcap_next_ex(handler, &pkt_header, &pkt_data)) {
for (int k = 0; k < 66; k++) {//输出每个包的前66个byte数据
if (k % 15 == 0 && k != 0)//输出美观
printf("\n");
printf("%02x ", *(pkt_data + k));
}
}
printf("\n");
}
getchar();
}
根据网络协议分层,数据包的格式为“|ethernet|ip|tcp/udp|http|”
具体的网络数据包,博主不打算讲,毕竟是winpcap快速入门,可能后续会推出网络数据包解析的博文
此处的数据包 packet
为博主从wireshare上复制的一个tcp syn的包,发送成功,则wireshark会接到数据大致相同的tcp synack包。如果要在自己的电脑上实现发包,需要自己使用wireshark抓取一个简单的包,复制其中的数据,填充至以下代码中的 packet
变量中,然后进行发包测试
#include
#include
#include
#define HAVE_REMOTE
int main() {
pcap_if_t * allDevs;
pcap_if_t * dev;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allDevs, errbuf) > 0) {
printf("pcap_findallDevs_ex failed\n");
}
for (dev = allDevs; dev->next != NULL; dev = dev->next) {
printf("----------------------------\n");
printf("name %s\n", dev->name);
printf("description :%s\n", dev->description);
}
int i = 0;
//找到连接到internet的网络设备
for (dev = allDevs, i = 0; i< 4; dev = dev->next, i++);
pcap_t * handler;
if (NULL == (handler = pcap_open(dev->name, 65535, PCAP_OPENFLAG_PROMISCUOUS, 3000, NULL, errbuf))) {
printf("err in pcap_open : %s", errbuf);
}
unsigned char packet[] = { 0x14,0x14,0x4b,0x80,0x40,0x81,0x54,0xee, 0x75,0x5e,0x6f,0xa8,0x08,0x00,
0x45,0x00, 0x00,0x34,0x77,0x44,0x40,0x00, 0x80,0x06,0x76,0xaf,0x0a,0x0a,0x2d,0xe9, 0x6f,0x0d,0x65,0xd0,
0xc3,0x67,0x00,0x50,0xaf,0xae,0x8c,0x23,0x00,0x00,0x00,0x00,0x80,0x02,0x20,0x00,0x42,0xb6,0x00,0x00,0x02,0x04,0x05,0xb4,0x01,0x03,0x03,0x08,0x01,0x01,0x04,0x02 };
if (1 != pcap_sendpacket(handler, packet, sizeof(packet))) {
printf("pcap_sendpacket failed");
}
getchar();
}