pcap文件分析-下之winpcap编程入门
0.环境、代码版本与编译器
windows + WpdPack_4_1_2.zip + visual studio 2005
1.winpcap工程概览
解开WpdPack_4_1_2.zip后,文件列表如下:
/*************************************************************************************************
├─docs //帮助文件
│ └─html
├─Examples-pcap //winpcap工程目录
│ ├─basic_dump //与basic_dump_ex一样,通过网卡实时抓包,只是接口有所不同
│ ├─basic_dump_ex
│ ├─iflist //获取物理网卡
│ ├─pcap_filter //pcap过滤保存
│ ├─pktdump_ex //抓取网卡报文,但不做协议解析
│ ├─readfile //与readfile_ex一样,读取pcap文件进行解析,只是接口有所不同
│ ├─readfile_ex
│ ├─savedump //通过网卡实时抓包,并保存为pcap格式文件
│ ├─sendpack //通过网卡发送构造的报文
│ └─UDPdump //通过网卡抓取UDP报文,同时进行简单的解析
├─Examples-remote //远程抓包实例,略过
├─Include //pcap相关的头文件
│ └─pcap
└─Lib //pcap库
└─x64
*************************************************************************************************/
建议大家在开始动手前,把docs中的帮助简单看一遍。上述的示例,其实归根到底主要是两方面,1)pcap离线分析,2)网卡实时抓包分析,其核心流程如下:
-
对于pcap文件的离线分析:
a)首先通过pcap_open_offline接口获取pcap文件句柄
b)接下来就可以通过pcap_next_ex或pcap_loop遍历文件句柄中的每一条报文了
-
对于通过网卡实时抓包,稍微复杂一点:
a)通过pcap_findalldevs接口,获取所有的网卡设备
b)选取抓包的网卡后,通过pcap_open_live接口获取网卡适配器的pcap文件句柄
c)接下来与上面一样,通过pcap_next_ex或pcap_loop即可实时获取网卡上的报文了
winpcap这里的设计思想与linux如出一辙:不论是设备还是文件,统一映射为文件进行管理,使得上层接口保持一致性。
说了这么多,winpcap到底能干嘛呢?别急,接下来我们看个示例。
2.pcap离线分析----获取Layer的密码字典
前段时间做web扫描,其中涉及到子域查询,用到了一款不错的工具《Layer 子域名挖掘机》,于是研究了一番,发现它进行子域查询时用了如下方式:
1.web API
Links.cn: http://i.links.cn/subdomain/'+ url +'.html (仍能正常工作)
Tools88 : http://www.tools88.com/safe/subdomain.php (查询界面还在,但接口不好使)
Locoy : http://chaxunapi.locoy.com/toolsAPI/getDomain (接口已失效)
2.DNS暴力查询
3.同服查询
站长工具:http://tool.chinaz.com/Same/ (接口已失效)
新接口 :http://s.tool.chinaz.com/same
其中DNS暴力查询比较引人注目,有内置字典“程序会自动使用内置字典,内置字典总共两万多条数据,内容包括了常用子域名,以及3000+常用单词和1-3位所有字母。”。哇,这就好比有个裤子在你面前,必须得脱下来~
但是怎么做呢?1.破解程序,这是个方法,但不在本文的讨论范围;2.DNS暴力破解,顾名思义就是用字典构造域名进行DNS请求,那么如果我们获取到它的DNS请求,不就有办法把字典给逆出来吗!
说干就干,这里先使用Layer2.1进行baidu.com的子域名查询,同时开启wireshark抓包:
静静等待一段时间让程序运行完成,然后我们进行wireshark过滤,将DNS暴力查询的报文过滤出来保存为dns.pcap文件:
之所以进行pcap的过滤,这是为了后续写解析代码时更简单。
对于winpcap工程,这里我选取readfile:
1.添加基本的ip头,udp头解析:
/* 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;
2.添加DNS解析代码:
void dns_handler(u_char *payload, int len) { char *start = payload + 13; char *end = payload + len - 5; char tmp[1024] = {0}; if (len <= (18 + strlen("baidu.com"))) return; while(start < end) { //if(*start == 0x05 || *start == 0x03 || *start == 0x04 || *start == 0x02 || *start == 0x06) if (*start < 20) *start = '.'; start++; } start = payload + 13; end -= strlen("baidu.com"); if( strncmp(end, "baidu.com", 9) == 0) { end -= 1; strncpy(tmp, start, end - start); printf("%s\n", tmp); } }
这里传入的payload是去除UDP头部后的应用层载荷,len是载荷的长度。
通过简单的+13,跳过了DNS请求头部的flag和字段信息,DNS查询时字符串并不是www.baidu.com这样的形式,查询时'.'处实际记录的是后面字符串的长度,具体可对照wireshark进行查看:
在程序中,简单粗暴的进行了处理,认为值小于20即是长度,将它替换为'.'即可。
最后我们去除尾部的.baidu.com,提取出前面的字符串,将它打印输出。
3.修改dispatcher_handler处理函数,让其进行报文头的简单解析,并调用dns_handler进行DNS处理:
void dispatcher_handler(u_char *temp1, const struct pcap_pkthdr *header, const u_char *pkt_data) { ip_header *ih; udp_header *uh; u_int ip_len; /* * unused parameter */ (VOID)(temp1); /* retireve the position of the ip header */ ih = (ip_header *) (pkt_data + 14); //length of ethernet header /* retireve the position of the udp header */ ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *) ((u_char*)ih + ip_len); dns_handler((char*)uh + 8, header->len - 14 - ip_len - 8); }
4.编译并运行,这样你就获取到了Layer所使用的字典了 :-)
readfile.exe dns_req.pcap > dict.txt
工程代码、dns.pcap、dict.txt等相关资源可在这里下载:http://pan.baidu.com/s/1hqCFHVe
注:这个程序只是一个最简单的demon,处理的是过滤后的dns.pcap文件,所以直接通过"ih + ip_len"获取到UDP头部,如果pcap文件中包含TCP报文,那么就不能这么简单的处理了,而是要依据ih->proto来判断具体的协议,再做进一步的decoder。
3.其它
看了上面的示例是否感觉意犹未竟,又或者觉得示例弱爆了,完全不能满足需求。哈哈,这里推荐IDF的开源项目:应用识别系统ORCHID,给大家做参考。该程序用于pcap文件的离线分析,主要功能与模块包括:
-
流量的分流:解析pcap文件,依据五元组信息进行分流(还记得上篇文章中提到的stream吗)
-
通过自定义特征,对流量进行扫描识别(用到了regex匹配和ac算法)
-
使用flex和bison进行应用特征的解析
-
针对windows和linux两个环境
-
该项目的目标是:做一款轻量级的、特征书写灵活的、高性能的应用识别引擎。
P.S. 因为笔者比较懒,所以项目也好久没更新了,平时忙于工作,好多快速匹配的idea也还没落实。欢迎感兴趣的小伙伴加入进来~
4.总结
对于pcap文件的分析,不论是工具还是编程,熟悉它们多使用,这样能提高你快速分析处理问题的能力,同时也别忘记加强对各种协议的学习。好了,《pcap文件分析》的文章就到这了,希望能帮助到你,谢谢~
P.S. 如果你有好的想法或者建议,不论是对于本文的,还是关于ctf,亦或者是对于IDF的,欢迎联系我们~
参考:
http://www.winpcap.org/devel.htm