首页 > 技术文章 > pcap文件分析-下之winpcap编程入门

HelloCodeWrold 2016-09-20 23:51 原文

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)网卡实时抓包分析,其核心流程如下:

  1. 对于pcap文件的离线分析:

    a)首先通过pcap_open_offline接口获取pcap文件句柄

    b)接下来就可以通过pcap_next_ex或pcap_loop遍历文件句柄中的每一条报文了

  2. 对于通过网卡实时抓包,稍微复杂一点:

    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文件的离线分析,主要功能与模块包括:

  1. 流量的分流:解析pcap文件,依据五元组信息进行分流(还记得上篇文章中提到的stream吗)

  2. 通过自定义特征,对流量进行扫描识别(用到了regex匹配和ac算法)

  3. 使用flex和bison进行应用特征的解析

  4. 针对windows和linux两个环境

  5. 该项目的目标是:做一款轻量级的、特征书写灵活的、高性能的应用识别引擎。

P.S. 因为笔者比较懒,所以项目也好久没更新了,平时忙于工作,好多快速匹配的idea也还没落实。欢迎感兴趣的小伙伴加入进来~

4.总结

对于pcap文件的分析,不论是工具还是编程,熟悉它们多使用,这样能提高你快速分析处理问题的能力,同时也别忘记加强对各种协议的学习。好了,《pcap文件分析》的文章就到这了,希望能帮助到你,谢谢~

P.S. 如果你有好的想法或者建议,不论是对于本文的,还是关于ctf,亦或者是对于IDF的,欢迎联系我们~

参考:

http://www.winpcap.org/devel.htm

http://www.cnseay.com/3816/


From: http://ctf.idf.cn/index.php?g=&m=article&a=index&id=11

推荐阅读