winpcap
FB招聘站
分类阅读
专栏
公开课
FIT 2019
企业服务
用户服务
搜索
投稿
登录
注册
WinPcap开发(一):零基础入门 追影人2016-05-05现金奖励共666486人围观 ,发现 16 个不明物体 系统安全网络安全
security_1950222c.jpg
*原创作者:追影人
0×00 前言
网络编程在网络安全方面具有举足轻重的作用,如何快捷高效的监听、分析、构造网络流量,成为很多安全从业者需要解决的重点问题。而winpcap这一免费开源项目恰好可以为win32应用程序提供访问网络底层的能力,所以其成为了相关网络编程的首选开发工具。
0×01 winpcap是什么?
winpcap(windows packet capture)是windows平台下一个免费的网络访问系统,可用于windows系统下的网络编程。著名的wireshark便是基于winpcap开发的,大家在安装wireshark中可以看到winpcap驱动程序的安装过程。
有关winpcap的介绍网络上很多,百科里面介绍的也很详细,我就不再copy了。需要注意的一点是,winpcap并不是一个简单的library,而是一个针对Win32平台上的抓包和网络分析的一个架构,它包括一个核心态的包过滤器,一个底层的动态链接库(packet.dll)和一个高层的不依赖于系统的库(wpcap.dll)。所以它只能“嗅探”到物理线路上的数据包,而不具备拦截的能力,因此不适用于个人防火墙等项目。
0×02 你需要准备些什么?
本系列文章主要带大家认识和了解如何利用winpcap网络编程技术进行网络的协议分析、流量统计及网络探测扫描等,这里我们并不会去深硬的解读相关源代码,而是以轻松的方式结合实验来对相关原理进行深入理解。在本系列文章中,笔者从简到难,简明介绍winpcap架构原理、相关环境搭建及快速编写核心代码。但是在开始前,读者需要有一些相关基础:了解网络协议相关基础知识,掌握一门winpcap开发库支持的编程语言,自己能动手实践编写一些例子。Winpcap提供的开发接口原生是c语言的,不过热心肠的程序猿们已经为其他语言的使用提供了封装,比如java、.net、python,好像连易语言都有。本系列文章将使用c语言来进行各种实验,有兴趣的读者可以将其转换成自己熟悉的语言来动手实践。
0×03 你能学到什么?
有关winpcap开发的文章在网上很容易找到,但是更多的都是对于代码的讲解,笔者在本文尽量系统性的从原理层面结合各个应用场景来介绍相关知识:
1. Winpcap获取网卡基本信息及收发数据包
2. 存活主机探测
3. 端口扫描
4. Arp欺骗
5. 中间人攻击的简单实现
6. 流量统计与分析
0×04 知识补充
进行下面的介绍前,我们需要了解几个名词的关系。
winpcap(windows packet capture)是windows平台下一个免费的网络访问系统,可用于windows系统下的网络编程。linux 平台下对应的开发包是libpcap。
Wireshark是基于winpcap处理网络驱动层。
Wpdpack是winpcap的开发包,提供开发相关程序的接口。
0×05 环境准备
首先根据你所选择的开发语言选择对应的编译器,笔者使用c语言,利用VS2012进行相关开发。
Clipboard Image.png
安装好编译器后,进行相关配置。下载wpdpack点击这里
初学者可以选择里面的Examples进行编译,可以看到找不到头文件,及相关库。
Clipboard Image.png
这是因为wpdpack中的相关库还没有引入到编译环境中
Clipboard Image.png
将wpdpack包中的Include和lib文件夹中的文件添加到VS的相关目录下即可编译通过。将编译后的程序进行运行则出现以下错误。
Clipboard Image.png
这是由于运行时缺乏动态链接库导致,最简单的方法是直接下载并安装winpcap驱动程序 下载
如果你觉得这样子很麻烦,也可以采用简易方法。程序在运行时只需要winpcap在system32下面释放的wpcap.dll和packet.dll,还有driver下面的npf.sys,所以不需要完整安装winpcap,而选择只复制以上三个文件到对应目录中即可。
本节笔者将采用著名的Arpspoof源码进行相关讲解,源码下载地址http://www.verysource.com/code/2287464_1/arpspoof.cpp.html
0×06 枚举可用网络适配器资源
在使用winpcap进行收发数据包时,需指定对应的网卡,所以有必要列出计算机上所有可用的网络适配资源。
列取网卡信息的核心代码:
//该函数在Arpspoof程序中,笔者进行了详细注释
void ListAdapters()
{
pcap_if_t *alldevs;//用于存储网卡链表的头指针
pcap_if_t *d;//用于遍历网卡链表的临时变量
int i = 0;//记录网卡个数
char errbuf[PCAP_ERRBUF_SIZE];//存储错误信息
char szGateIPAddr[16];//网卡对应网关地址
char *p;//网卡名词
char szIPAddr[16];//网卡对应IP
unsigned char ucPhysicalAddr[6];//网卡对应的MAC地址
if (pcap_findalldevs(&alldevs, errbuf) == -1)//获取网卡链表
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
return;
}
for (d=alldevs; d; d=d->next)//遍历网卡链表
{
if (d->addresses != NULL && (p = strchr(d->name, '{')) != NULL
&& Getadapterbyname(p, szIPAddr, ucPhysicalAddr,szGateIPAddr))//获取网卡的对应信息
{
for(int j = strlen(d->description) - 1; j > 0; j--)//对网卡的描述信息格式化
{
if (d->description[j] == 0x20)
d->description[j] = '';
else
break;
}
printf("\n %d. %s\n\tIP Address. . . . . : %s\n", i, d->description, szIPAddr);//格式化输出网卡信息
printf("\tPhysical Address. . : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",
ucPhysicalAddr[0], ucPhysicalAddr[1], ucPhysicalAddr[2],
ucPhysicalAddr[3], ucPhysicalAddr[4], ucPhysicalAddr[5]);
printf("\tDefault Gateway . . : %s\n", szGateIPAddr);
i ++;
}
}
if (i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return;
}
pcap_freealldevs(alldevs);//释放网卡链表
}
科普Tips:
“网卡”是神马?
计算机与外界局域网的连接是通过主机箱内插入一块网络接口板(或者是在笔记本电脑中插入一块PCMCIA卡)。网络接口板又称为通信适配器或网络适配器(network adapter)或网络接口卡NIC(Network Interface Card),但是更多的人愿意使用更为简单的名称“网卡”。
利用上面的程序,我们可以查看计算机上可利用的所有网卡资源,以便选择相应的网卡资源进行相关操作。为了便于观察,我们在VMware虚拟机中进行,首先在对应的虚拟机设置中增加硬件选项中添加多块网卡,然后配置相应的IP,运行程序,可以得到对应网卡的名称描述、IP地址、MAC地址等。
Clipboard Image.png
Clipboard Image.png
0×07 如何构造和发送数据包
上一步我们列出了所有的可用网卡资源,在发送数据包前,需要打开对应的网卡来进行发送数据包的操作。这里使用的函数是pcap_open_live:
函数名称:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
函数功能:获得用于捕获网络数据包的数据包捕获描述字。
参数说明:device参数为指定打开的网络设备名。snaplen参数定义捕获数据的最大字节数。promisc指定是否将网络接口置于混杂模式。to_ms参数指定超时时间(毫秒)。ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。
返回值:打开的网卡句柄
Arpspoof中将网卡的打开操作进行了如下封装,调用时直接输入网卡序号即可,程序会对参数2、3、4进行初始化设置:
pcap_t* OpenAdapter(int uIndexofAdapter, char szIPSelf[],
unsigned char ucPhysicalAddr[], char szGateIPAddr[])
{
pcap_if_t *alldevs;
pcap_if_t *d;
pcap_t *fp = NULL;
int i = 0;
char errbuf[PCAP_ERRBUF_SIZE], *p;
/* 这个API用来获得网卡的列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
return NULL;
}
/* 显示列表的响应字段的内容 */
for (d=alldevs; d; d=d->next)
{
if (d->addresses != NULL && (p = strchr(d->name, '{')) != NULL
&& Getadapterbyname(p, szIPSelf, ucPhysicalAddr, szGateIPAddr))
{
if (i == uIndexofAdapter)
{
if ((fp = pcap_open_live(d->name, // 设备名称
65536, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
1, // 混杂模式
1, //读超时为1ms,越小越好
errbuf // error buffer
)) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. \
%s is not supported by WinPcap\n", d->name);
pcap_freealldevs(alldevs);
return NULL;
}
else
{
// 去掉网卡注释右边的空格
for(int j = strlen(d->description) - 1; j > 0; j--)
{
if (d->description[j] == 0x20)
d->description[j] = '';
else
break;
}
printf("[*] Bind on %s %s ...\n", szIPSelf, d->description);
return fp;
}
}
i ++;
}
}
if (i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return FALSE;
}
/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
return NULL;
}
使用范例:
pcap_t *adhandle; // 网卡句柄
unsigned char ucSelf[6];
char szIPSelf[16], szIPGate[16];
if ((adhandle = OpenAdapter(0, szIPSelf, ucSelf, szIPGate)) == NULL)
{
printf("[!] Open adatper error!\n");
return FALSE;
}
在获取到网卡句柄并打开后,发送数据包就很容易了
if(pcap_sendpacket(adhandle, (const unsigned char *) ucFrame,
ucFrameLen) < 0) { printf("Send Packet Error\n"); return FALSE; } ucFrame是封装好的数据包,ucFrameLen为数据包的长度。 下面我们封装一个例子,使用上述代码发送ARP请求包,用于查询某IP对应的MAC地址。 ARP协议格式 Clipboard Image.png 关键代码 bool sendARPData(pcap_t *adhandle) { u_char ucFrame[ARP_LEN]; // 设置Ethernet头 ETHeader eh = { 0 }; memset(eh.dhost,0xff, 6);//ARP广播包目的地址为ffffffffffff memcpy(eh.shost, ucSelf, 6); eh.type = htons(ETHERTYPE_ARP);//帧类型为ARP memcpy(ucFrame, &eh, sizeof(eh)); // 设置Arp头 ARPHeader ah = { 0 }; ah.hrd = htons(ARPHRD_ETHER); ah.eth_type = htons(ETHERTYPE_IP); ah.maclen = 6;//硬件地址长度 ah.iplen = 4;//IP地址长度 ah.opcode = htons(ARP_REQUEST);//ARP请求包类型 memcpy(ah.smac, ucSelf, 6); ah.saddr = inet_addr(szIPSelf); memset(ah.dmac, 0x00, 6);//ARP请求包中目的MAC地址均置0 ah.daddr = inet_addr("192.168.0.2"); //ARP请求的目的IP地址 memcpy(&ucFrame[sizeof(ETHeader)], &ah, sizeof(ah)); // 发送ARP数据包 if(pcap_sendpacket(adhandle, (const unsigned char *) ucFrame,ARP_LEN) < 0) { printf("Send Packet Error\n"); return FALSE; } return TRUE; } 启动wireshark进行监听,运行程序,我们可以看到如下结果,程序发出了一个ARP广播包,用于查询192.168.0.2的主机MAC,并且目标机在收到该查询包后,进行了回复,将自己的MAC地址告诉了查询发起的机器。 Clipboard Image.png 0×08 如何监听分析数据包 在监听数据包时,使用的关键函数为pcap_loop 函数名称:int pcap_loop(pcap_t * p,int cnt, pcap_handler callback, uchar * user); 参数说明: p 是由pcap_open_live()返回的所打开的网卡的指针; cnt用于设置所捕获数据包的个数; callback 是回调函数,其原型为pcap_callback(u_char* argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content) ;user值一般为NULL 结合上面的代码,我们在获得并打开网卡句柄adhandle,使用下面的代码并可捕获数据包 //每次捕捉到数据包时,pcap都会自动调用这个回调函数 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { struct tm *ltime; char timestr[16]; time_t local_tv_sec; //将时间戳转换成可识别的格式 local_tv_sec = header->ts.tv_sec;
printf("%d \n", local_tv_sec);
ltime = localtime(&local_tv_sec);
strftime(timestr, sizeof(timestr), "%H %M %S", ltime);
printf("%s,%.6d len:%d\n", ctime(&local_tv_sec), header->ts.tv_usec, header->len);
}
pcap_loop(adhandle, 0, packet_handler, NULL);
程序在每一个数据包到来时,都会自动调用回调函数packet_handler来对数据包进行处理,其第三个参数便是数据包内容。
Clipboard Image.png
上图为运行结果图,可以看到每一个数据包的时间戳信息,和长度信息。
值得注意的是,原始套接字也可以完成数据包的发送和监听工作,但是与winpcap相比,在监听数据包方面是有区别的,由于winpcap更接近与底层,所以在混杂模式下,凡是到达网卡的数据包不管目的地址是否为自身主机,winpcap均能接收到;而原始套接字只能接收到投送给自己的数据包。
0×09 总结与预告
本章中我们简单认识了winpcap的相关基础知识,学习了发送数据包和接收数据包的方法,其实不难发现,发送和接收数据包的过程都比较简单,只需要调用相关库函数即可,而更多的精力在数据包的组织和拆分上,同时在一些场景中,算法的使用也较为重要。在接下来的章节中,我们会看到下面的内容:
1.扫描存活主机
2.Arp欺骗的实现与应用
3.端口扫描
4.流量监控与统计分析
*本文作者:追影人,本文属FreeBuf原创奖励计划,转载须联系editor@tophant.com
追影人
追影人
14 篇文章
等级: 5级
||
上一篇:隐藏在图片中的恶魔:揭秘“数字隐写术”工作原理下一篇:美国将研究一新技术用来识别和跟踪全球的黑客
这些评论亮了
mmc (4级)回复
这都能作为原创奖励文章!我只想知道一篇文章多少钱!
)12(亮了
cwg2552298 (6级)Follow my own course回复
谢谢分享!
)9(亮了
Thoxvi 回复
好棒的样子
)8(亮了
ysc3839 回复
关于易语言我想说,自带的一个支持库里就有调用WinPcap发送ARP请求的功能,当时搞了半天搞出了一个攻击让别人掉线的软件,结果被发现了………………
)8(亮了
我是石头 回复
pcapy,python下基于winpcap的package,挺好用的
)7(亮了
发表评论已有 16 条评论
Thoxvi 2016-05-05回复 1楼
好棒的样子
亮了(8)
我是石头 2016-05-05回复 2楼
pcapy,python下基于winpcap的package,挺好用的
亮了(7)
mmc (4级) 2016-05-06回复 3楼
这都能作为原创奖励文章!我只想知道一篇文章多少钱!
亮了(12)
常运 专栏作者(6级) c4td0g, 信安从业者,信安爱好者。(各位爷,轻点喷),... 2016-05-06回复 4楼
…………………………………………………………….
这都能作为原创奖励文章!我只想知道一篇文章多少钱!
亮了(6)
常运 专栏作者(6级) c4td0g, 信安从业者,信安爱好者。(各位爷,轻点喷),... 2016-05-06回复 5楼
目测帖主是刚接触这块的吧?加油哈
亮了(6)
cwg2552298 (6级) Follow my own course 2016-05-06回复 6楼
谢谢分享!
亮了(9)
fulyxu (1级) 2016-05-06回复 7楼
抽时间研究一下。
亮了(6)
ysc3839 2016-05-07回复 8楼
关于易语言我想说,自带的一个支持库里就有调用WinPcap发送ARP请求的功能,当时搞了半天搞出了一个攻击让别人掉线的软件,结果被发现了………………
亮了(8)
吴涛 2016-05-09回复
@ ysc3839 WinPcap是底层的网络接口调用,易语言那个是LSP应用层的,完全不一样。
亮了(5)
kin-sun (1级) 2016-05-08回复 9楼
:shock:
:grin:
亮了(6)
木千之 (5级) 人,既无虎狼之爪牙,亦无狮象之力量,却能擒狼缚虎,驯狮猎象,... 2016-05-09回复 10楼
我觉得从开发角度来说,pytyon比较容易上手,winpcap库在windows上的效率不如libpcap在linux上更好,其实就是觉得捕包分析实际应用还是Linux环境更好一些:)
亮了(5)
安静百合sky (1级) 2016-05-10回复 11楼
@追影人 可以给出程序源码不?重现不了效果呢,谢谢
亮了(4)
追影人 (5级) weibo.cn/KOshadow 2016-05-11回复
@ 安静百合sky 你好,本章所用代码全部来源于ARPSPOOF源码,文中提供了下载地址
亮了(5)
静静hack (2级) 2016-06-03回复 12楼
下载地址为什么不是github
亮了(0)
三只松鼠 (1级) 做正确的事 2017-09-11回复 13楼
蛮基础的,简洁明了,感谢笔者分享。
亮了(0)
xiaoqianxiansheng (1级) 2017-11-10回复 14楼
你好! 看了这个帖子 发现 Getadapterbyname 这个函数 是哪里的接口? winpacp 并没有查到 可是文章没有关于这个 函数的更多提示 。还是哪里有整个工程的下载地址。
亮了(0)
昵称
请输入昵称
必须您当前尚未登录。登陆?注册邮箱
请输入邮箱地址
必须(保密)表情插图
有人回复时邮件通知我
追影人
追影人
weibo.cn/KOshadow
14
文章数
116
评论数
最近文章
“数”说wannacry的比特币钱包
2017.06.01
局域网聊天软件攻防战
2017.05.04
那些年我们一起守护的“密”
2017.04.05
浏览更多
相关阅读
WinPcap开发(一):零基础入门局域网聊天软件攻防战BT5 + wireshark玩wifi捕获和中间人攻击用Wireshark简单分析HTTPS传输过程-抓包过程Wireshark1.6.8 Released
特别推荐
关注我们 分享每日精选文章
活动预告
11月
FreeBuf精品公开课·双11学习狂欢节 | 给努力的你打打气
已结束
10月
【16课时-连载中】挖掘CVE不是梦(系列课程2)
已结束
10月
【首节课仅需1元】挖掘CVE不是梦
已结束
9月
【已结束】自炼神兵之自动化批量刷SRC
已结束
FREEBUF免责声明协议条款关于我们加入我们广告及服务寻求报道广告合作联系我们友情链接关注我们
官方微信
新浪微博腾讯微博Twitter赞助商
Copyright © 2018 WWW.FREEBUF.COM All Rights Reserved 沪ICP备13033796号
0daybank
文章评论