您好,欢迎来到筏尚旅游网。
搜索
您的当前位置:首页数据包捕获与解析

数据包捕获与解析

来源:筏尚旅游网
.

数据包捕获与分析

摘 要 本课程设计通过Ethereal捕捉实时网络数据包,并根据网络协议分析流程对数据包在TCP/IP各层协议中进行实际解包分析,让网络研究人员对数据包的认识上升到一个感性的层面,为网络协议分析提供技术手段。最后根据Ethereal的工作原理,用

Visual C++编写一个简单的数据包捕获与分析软件。

关键词 协议分析;Ethereal;数据包;Visual C++

1引言

本课程设计通过技术手段捕获数据包并加以分析,追踪数据包在TCP/IP各层的封装过程,对于网络协议的研究具有重要的意义。Ethereal是当前较为流行的图形用户接口的抓包软件,是一个可以用来监视所有在网络上被传送的包,并分析其内容的程序。它通常被用来检查网络工作情况,或是用来发现网络程序的bugs。通过ethereal对TCP、UDP、SMTP、telnet和FTP等常用协议进行分析,非常有助于网络故障修复、分析以及软件和协议开发。,它以开源、免费、操作界面友好等优点广为世界各地网络研究人员使用为网络协议分析搭建了一个良好的研究平台。

1.1课程设计的内容

(1)掌握数据包捕获和数据包分析的相关知识;

(2)掌握Ethreal软件的安装、启动,并熟悉用它进行局域网数据捕获和分析的功能; (3)设计一个简单的数据包捕获与分析软件。

.

.

1.2课程设计的要求

(1)按要求编写课程设计报告书,能正确阐述设计结果。

(2)通过课程设计培养学生严谨的科学态度,认真的工作作风和团队协作精神。 (3)学会文献检索的基本方法和综合运用文献的能力。

(4)在老师的指导下,要求每个学生完成课程设计的全部内容。

1.3课程设计平台

Windows XP;Ethereal;Visual C++

2使用Ethereal对数据包进行捕获与分析

2.1软件Ethereal 简介

Ethereal (Ethereal:A Network Packet Sniffing Tool)是当前较为流行的一种计算机网络调试和数据包嗅探软件。Ethereal 基本类似于tcpdump,但Ethereal 还具有设计完美的 GUI 和众多分类信息及过滤选项。用户通过 Ethereal,同时将网卡插入混合模式,可以查看到网络中发送的所有通信流量。 Ethereal 应用于故障修复、分析、软件和协议开发以及教育领域。它具有用户对协议分析器所期望的所有标准特征,并具有其它同类产品所不具备的有关特征。Ethereal 主要具有以下特征:

在实时时间内,从网络连接处捕获数据,或者从被捕获文件处读取数据;Ethereal 可以读取从 tcpdump(libpcap)、网络通用嗅探器(被压缩和未被压缩)、SnifferTM 专业版、NetXrayTM、Sun snoop 和 atmsnoop、Shomiti/Finisar 测试员、AIX 的 iptrace、Microsoft 的网络监控器、Novell 的 LANalyzer、RADCOM 的 WAN/LAN 分析器、 ISDN4BSD 项目的 HP-UX nettl 和 i4btrace、Cisco 安全 IDS iplog 和 pppd 日志( pppdump 格式)、WildPacket 的 EtherPeek/TokenPeek/AiroPeek 或者可视网络的可视 UpTime 处捕获的文件。此外 Ethereal 也能从 Lucent/Ascend WAN 路由器和 Toshiba ISDN 路由器中读取跟踪报告,还能从 VMS 的 TCPIP 读取输出文本和 DBS Etherwatch。 从以太网、FDDI、PPP、令牌环、IEEE 802.11、ATM 上的 IP 和回路接口(至少是某些系统,不是所有系统都支持这些类型)上读取实时数据。 通过 GUI 或 TTY 模式 tethereal 程序,可以访问被捕获的网络数据。通过 editcap 程序的命令行交换

.

.

机,有计划地编辑或修改被捕获文件。 当前602协议可被分割。 输出文件可以被保存或打印为纯文本或 PostScript格式。 通过显示过滤器精确显示数据。 显示过滤器也可以选择性地用于高亮区和颜色包摘要信息。所有或部分被捕获的网络跟踪报告都会保存到磁盘中[1]。

2.2 利用Ethereal捕获数据包

安装完Ethereal后,单击Capture下的Option菜单,打开捕获选项对话框,设置好捕捉接口(interface)和过滤器(capture filter),设置混杂模式(promiscuous mode)选项(此选项使得网卡并不检验数据帧的目的地址,用以截获网上的任何帧),其他选项可采用默认设置如图2-1,再单击Start按钮即可实时截获数据包。用Ethereal的捕获窗口如图2-2,捕获到的实时网络数据包的部分截图见图2-3。所截获的数据包分别在包列表(PackList)、包细节(Packet Details)和包字节(PackeBytes)三栏窗口中显示。其中上栏的包列表窗口按截获的时间顺序显示出数据包的基本信息:编号(代表收到数据包的次序)、时间、源地址、目的地址协议名称以及关于此数据包的摘要信息;中间栏的包细节窗口以树形显示当前数据包在各协议层的封装细节,包括首部和数据;下栏的包字节窗口则以十六进制和ASCII码显示被截获数据包的详细内容左边一栏显示偏移量,中间一栏显示十六进制数值,右边一栏显示解码后相对应的字符(控制字符示为1个点)。

.

.

图2-1Ethereal的设置

图2-2捕获状态窗口

.

.

图2-3捕获的数据包

2.2 利用Ethereal对捕获数据包进行分析

Ethereal是当前较为流行的一种计算机网络调试和数据包嗅探软件,是一个可以用来监视所有在网络上被传送的包,并分析其内容的程序。它通常被用来检查网络工作情况,或是用来发现网络程序的bugs。通过ethereal对TCP、UDP、SMTP、telnet和FTP等常用协议进行分析,非常有助于网络故障修复、分析以及软件和协议开发。 (1)ARP协议分析

ARP,全称Address Resolution Protocol,地址解析协1它工作在数据链路层,在本层和硬件接口联系,同时对上压供服务。TP数据包常通过以太网发送,以太网设备并不识别32IP地址,它们是以48位以太网地址传输以太网数据包。必须把IP目的地址转换成以太网目的地址。因此,在以太网中,一个主机要和另一个主机进行直接通信,必须要知道目标主机的MAC地址。但这个目标MAC地址是如何获得的呢?它就是通过地址解析协议获得的。图2-4就是对ARP捕获的状态窗口。ARP协议用于将网络中的IP地址解析为的硬件地址(MAC地址),以保证通信的顺利进行。网络当中经常会使用到ARP协议,所以可以使用Ethereal抓取网络中的ARP数据包,如图2-5,从图2-5中看到,已经捕获到了一些ARP的数据包,每个数据包占一行,比如第1个ARP数据包,从它的info信息里面可以看到对于这个数据包的简要的说明:Who has 10.28.23.140? Tell 10.28.23.250。这个info表明ARP协议的主要功能:通过IP地址找对方的MAC地址。针对ARP协议还可以具体分析它的结构,以往的教学中学生只能从课本上看到ARP协议的图,如图6,学生容易产生疑问,难道真的是这样吗?在我们可以通过分析抓取到的数

.

.

据包来切切实实地看一下它的结构到底是什.么样的,对照图2-6看一下到底是不是一致。随便找一个ARP的数据包,将其展开可以看到图2-7的结构,对比图2-7中框部分与图2-6中框部分,可以发现两者是一致的,通过对比学生就会对ARP的结构有更深刻的认识[2]。

图2-4ARP捕获状态窗口

图2-5捕获的ARP数据包

.

.

硬件地址长度协议地址长度以太网目的地址以太网源帧类硬件类协议地址型型类型OP发送端以太网地址发送端IP目的以太网目的IP地地址地址址

图2-6ARP报文结构

图2-7ARP结构

(2)利用Ethereal分析TCP/IP机制

TCP是一种面向连接的、可靠的传输层协议,TCP数据传(只有连接建立后才可进行数据传输)需要通过在客户端和服端建立特定的虚电路连接来完成,该过程通常被称为“三次握手”,如图2-8,即发送方先发送连接请求,然后接受方进行连接确认,最发送方对接受方再次进确认。下面就以Ethereal捕获的建TCP连接过程的三个数据包为例对TCP/IP协议进行分析。

.

.

SYN,SEQ=xSYN,SEQ=y,ACK=x+1ACK=y+1

图2-8三次握手示意图

为了能够捕获到“三次握手”过程中的数据包,首先让Ethereal一直保持捕获状态(图2-9),因为是通过TCP来建立的,可以将Ethereal的过滤器设置为TCP,此时只捕获所有经过计算机的TCP协议数据包。

图2-9TCP捕获状态窗口

在保持捕获的状态下,打开一个新的网页,如http://www.163.com,由于访问网页首先需要通过“三次握手”建立连接,然后才能进行数据的传输,此时,Ethereal就可以捕获到在访问网页过程中建立连接的TCP数据包(图2-10)

.

.

图2-10 TCP捕获状态窗口

在捕获状态窗口中点击停止,将所有捕获到的数抿所显示出图2-11显示的就是所捕到的前4个数据包,从图中可以看到1号数据包一3号数据包是连接建立过程中的数据包,4号数据包是在连接建立完成以后开始传输数据。

图2-11捕获到的数据包

客户端发送连接请求,从图2-12可以看出,该数据包封装了三个头信息:以太网(Eth-ernet)帧、IP数据报(IP数据报首部格式如图2-12)和TCP报文段(TCP报文段固定首部格式如图2-13)。在物理链路层,数据以帧的方式进行传输。以太网帧头信息中,描述了该数据包的接收方MAC(MAC的结构如图2-14)地址为00:03:0f:00:0c:4b发起连接请求的源主机MAC为00:03:0d:a4:0f:72,在帧中封装的协议类型type值为0x0800,即IP数据报。在网络层,加工的主要数据对象是IP数据报。IP协议是TCPIP协议族中的核心协议之一,所有的TCP、UDP、ICMP数据都以IP数据报格式传输。从以上请求数据包的IP首部可以看出,此IP数据报版本号(version)为4(即这个数据报为IPv4),首

.

.

部(head length)为20bytes,服务类型(services field)为0x00,数据报总长(total length,即IP首部+数据载荷)为48,标识(identification)为0x96b53,标志(flags)为0x04表示报文不分段,段偏移(fragmen offset)为0,生存时间(time to live)为128,数据报中上层协议类型protocol值为0x06 (即TCP报文段),头部校验和0x1206表示正确,请求主机的IP地址为10.10.23.226,目的主机的IP地址为58.248.245.40。在运输层,主要数据对象是TCP报文。在以上的TCP报文段中,描述了请求方源端口号(source port)为1615;目的端口号(destination port)为80,其中0是HTTP协议的保留端口号;序列号SEQ是本次连接的初始序号,因此在连接请求时相对初始值是0,其实际值是24 68 15 a1;确认号是00 00 00 70;头度(header length)为28bytes;标志位(flags)为Ox0002,指示ACK标志为0表明确认号被忽略,SYN=1表示正在进行连接请求,通过SYN和ACK也可以用来区分Connection Request和Connection Accepted,在连接请求中,SYN=1、ACK=0,连接响应时,SYN=1、ACK=1;PSH为0;窗口字段(window size)指示发送方想要接收的最大字节数为65535;校验和(checksum)为0xf6a表明正确;最后是8bytes的选项字段[3]。

比特0 4 8 16 19 24 31

版本首度标识生存时间协议源地址目标地址服务类型标志首部检验和总长度片偏移 图2-12 IP数据报首部格式

比特 0 8 16 24 31

源端口序号确认号目的端口数据偏移保留URGACKPSHPSTSYNFIN窗口检验和紧急指针

图2-13 TCP报文段固定首部格式

.

.

字节 6 6 2 46-105 4

目的MAC地址源MAC地址类型数据FCS

图2-14以太网V2 MAC帧格式

图2-15发送方发出的连接请求数据包

对此数据包的具体分析过程如图2-12,在此我们仅涉及连接的过程中一些重要地方的变化:数据包由服务端58.248.245.40发至客户端10.10.23.226。在响应TCP报文段中,源端口和目的端口地址相对改变,相应数据包的起始序列号SEQ为ef 84 c8 9b,确认号为24 68 17 a2 (实际上是请求数据的起始序号加1,也表示下一个希望接收的数据的起始位置),标志位0x0010指示ACK标志为1表明确认号有效、SYN仍然为1。

.

.

图2-16服务端响应数据包

客户端连接确认在TCP连接建立的最后阶段如图2-17,客户端对接受到的服务器相应进行确认,到此为止建立完整的TCP连接,开始全双工模式的数据传输过程。图2-17客户端确认数据包在确认阶段,数据包由客户端10.10.23.226发送至服务端58.248.245.40,TCP中的序列号为24 68 15 a2(即上次服务器响应报文的确认号),报文段中的本次确认号为73 ff 17 ff(即上次的序列号加1)表示客户端下一次希望从主机接收的数据的起始位置;标志位Ox0010指示ACK标志为1表明确认号有效,SYN置为0表示连接建立结束。通过上述利用Ethereal对TCP连接过程的三个数据包的分析,可以看出TCP/IP协议的Three-way handshaking过程如下:第一步,客户端发出连接请求,TCP数据为:SEQ=24 68 15 a2,ACKNUM=00 00 00 00,SYN=1,ACK=0。第二步,服务端确认可以连接,TCP数据为:SEQ=ef 84 c8 9b,ACKNUM=24 68 15 a2,SYN=1,ACK=1。第三步,客户端建立连接,TCP数据为:SEQ=24 68 15 a2,ACKNUM=ef 84 c8 9b,SYN=0,ACK=1。TCP/IP协议是一个协议族,包含大小上百个协议和标准。通过以上对TCP连接过程的分析,只是提出了使用Ethereal进行协议分析的思路和方法,使用Ethereal也可方便地对其它协议进行分析,例如分析HTTP协议的客户端请求与服务器应答过程及它们的头部格式,分析ICMP协议的错误报告和信息反馈机制等,具体分析方法与上面的分析相似,这里不再赘

.

.

述[4]。

图2-17客户端确认数据包

3用Visual C++设计一个简单的数据包捕获和分析软件

3.1 Visual C++简介

Visual C++即VC,微软公司出品的高级可视化计算机程序开发工具。他提供了一套开发环境:Visual Studio,Visual Studio本身包括一个文本编辑器、资源编辑器、工程编译工具、一个增量连接器、源代码浏览器、集成调试工具,以及一套联机文档,借助这套工具,用户可以随心所欲地开发出各种功能的应用软件以及借助OpenGL和DirectX技术开发游戏软件。Visual C++可以识别C/C++并编译,支持MFC类库,并提供了一系列模板,常用的MFC AppWizard(EXE/DLL),MFC ActiveXControlWizard,Win32Application,Win32ConsoleApplication,ATLCOMAppWizard。这种可视化编程环境可以令程序员花更多精力在程序功能的实现上,而不是底层的建设上,这就大大加快了程序开发速度和效率,这也是Visual C++一个显著的特点。利用Visual C++编译出的程序空间小,运行快,比其他的编译工具编译出的软件占据较多优势。现在常用的版本有Visual C++ 6.0/.Net/2005[5]。

.

.

3.2WinPcap简介

WinPcap是一个在Windows操作系统下的免费、公开的用于直接访问网络的开发工具包(编程API)。大多数Windows网络应用程序都是通过Winsock API(Windows套接口)这类高级编程接口访问网络的。这种方法允许在网络上进行简单的数据传送,因为操作系统的TCP/IP协议栈实现软件会处理底层细节(协议操作、流程重组等等),并提供一个类似于读写文件的函数接口。然而,有时候“简便方法”并不能满足实际需要。有些程序希望绕过TCP/IP协议栈,直接处理底层网络中的通信数据,它们需要对网络进行底层进行直接访问,即在没有类似协议栈(TCP/IP协议栈)的实体介入条件下对网络进行原始访问。基于Winsock API编程,应用程序是通过调用操作系统提供的编程接口访问TCP/IP协议栈实现网络通信的。基于WinPcap编程,网络程序实际上是绕开操作系统的TCP/IP协议栈直接通过底层网络发送数据,因此网络程序可以实现一些更低级、更灵活的功能[6]。

3.3建立工程

在VC++ 6.0下创建一个单文档的MFC应用程序,工程名:Sniffer如图3-1->图3-2->图3-3。

图3-1建立工程

.

.

图3-2选中单文档

图3-3自动生成的类列表

到http://www.winpcap.org/devel.htm下载WinPcap 4.0.2.zip,然后解压,解压缩就可以看见Includelib;在\"Project->Settings\"标签栏中选择\"C/C++\",在\"Preprocessor definitions\"的输入框里添加\"WPCAP\";再选择\"Link\",在\"Object/library modules\"的输入框里添加\"wpcap.lib \"。然后再设置VC++环境变量:选择Tools->options->Directories的include里面加入下载的winpcap开发包解压以后的include文件选择Tools->options->Directories的lib里面加入下载的winpcap开发包解压以后的lib文件夹[7]。

3.4进行界面的设计

工程建好了,下面进行界面的设计:

首先,对菜单栏进行修改,去掉原来单文档所自带的“文件”、“编辑”菜单选项,保留“查看”和“帮助”,新建“文件”,下面有“开始抓包(ID_FILE_START)”、“停止抓包(ID_FILE_STOP)”、“退出(ID_APP_EXIT)”三个菜单选项。再建“适配器”菜单,下面有“选择适配器(ID_ADP_CHOOSE)”选项,并对每个新建的选项进行注释说明。如图3-4:

.

.

图3-4 菜单栏

然后,打开Sniffer.rc文件,对工具栏进行修改。自做了一个工具栏图片Toolbar1.bmp来代替原来工程的Toolbar.bmp,然后将多余的复制粘贴等工具按钮信息删除掉,回到界面处,再对每个按钮图标进行ID设置。如图:左向右依次是:开始抓包、停止抓包、选择适配器、帮助图标按钮。

最后,新建一个选择适配器的基本对话框,ID标识为IDD_ADP_DIALOG,双击此对话框新建一个类:CAdpterDlg。在此基本对话框上拖入一个Tree Contrl控件和List Contrl控件,对控件属性界面进行调整,打开类向导,将Tree Contrl成员变量设置为:m_treeCtrl,List Contrl成员变量设置为m_listCtrl。如图3-5:

,从

图3-5 选择适配器对话框

3.5程序设计思想

本程序中,主要有四种类型的类,主控类:CMainFrame,视图类:CCapPackView、

.

.

CProTreeView,对话框类:CAdpterDlg以及报文类。图3-6为整体的类之间的调用流程图。

IPGram类:CMainFrame类:CAdpterDlgOnInitDialog()OnClickAdpTree()选中适配器GetService()获取协议类型GetDestAddr()获取目的IP点击:适配器->选择适配器点击:文件->开始抓包OnOK()点击按钮,绑定网卡类:CProTreeViewOnInitialUpdate()界面设置GetDestAddr()获取目的IP启动收包线程点击:退出判断类型,若为数IP类:CCapPackViewOnInitialUpdate()界面设置包OnPacketSelect()以树形结构显示选中的包的具体信息用ARPGramRARPGram显示所有抓到的包的简要信息判AR断类P/R型,AR若P数为据包GetSrcHdwAddr()包发送方MACGetSrcPrtAddr()包发送方IPGetDestHdwAddr()包接收方MACGetDestPrtAddr()包接收方IPEtherHeadGetMacSrcAddr()包源MAC地址GetMacDestAddr()包目的MAC地址GetType()获取数据包类型通知ProTreeView刷新为新选中的报文内容调据 图3-6总体类调用流程图

CMainFrame,是用于主控的类,它起到分区、处理消息、传递消息的功能。将用户区分为两个视图,点击菜单里的按钮,触发打开适配器对话框或者开始抓包、停止抓包的动作。图3-7为CMainFrame类中方法调用流程图。表3-1 CMainFrame类说明为CMainFrame函数成员的说明。

表3-1 CMainFrame类说明

CMainFrame类 父类 .

CFrameWnd类 . 成员函数 OnCreateClient() 参数 LPCREATESTRUCT lpcs, CCreateContext* pContext 功能 将用户区分为左右两个视图ProTreeView、CapPackView OnAdpChoose() 消息处理函数 无 为适配器对话框初始化值,即点击选中适配器按钮弹出适配器对话框 OnFileStart() 消息处理函数 无 设置抓包状态,释放所有包,清空内容,启动收包线程,开始捕获包。 OnFileStop() 消息处理函数 OnUpdateFileStart() 消息处理函数 OnUpdateFileStop() 消息处理函数 成员变量 *PackView *ProTreeView 无 停止抓包 CCmdUI* pCmdUI 当在捕获包时,禁用“抓包”按钮 CCmdUI* pCmdUI 当停止捕获包时,禁用“停止”按钮 类型 CCapPackView CProTreeView 含义 显示所有抓到的包的简要信息 显示选中的包的具体信息,用解析树表达 *alldevs *dev isStart isStop pcap_if_t pcap_if_t bool bool 适配器链表 适配器链表 是否开始抓包 是否停止抓包 .

.

类:CMainFrame成员变量初始化OnFileStop()停止捕获包点击:适配器->选择适配器调用Pcap_handle()回调函数OnAdpChoose()选择适配器调用Pcap_loop()捕获包OnFileStart()当网卡绑定后,启动抓包线程ReceivePacketpcap_open_live()打开网卡

图3-7 CMainFrame类中方法调用流程图

CAdpterDlg:对话框类,此对话框分为两部分:树形控件和list控件。当对话框被触发后,树形控件显示了本机所有的适配器列表,双击选中网卡,list控件显示其名称、描述、子网掩码、IP地址等信息。点击确定按钮即绑定了此网卡,注意虚拟网卡是不能被绑定的。表3-2为类CAdpterDlg的成员函数及成员变量的说明。CAdpterDlg类中函数调用流程图如图3-8所示。

表3-2 CAdpterDlg类说明

CAdpterDlg类 父类 成员函数 OnInitDialog() 公有 CDialog类 参数 无 功能 初始化树形控件,设置list控件,读取适配器并将适配器列表显示在树形控件中。当网卡绑定以后再次打开此对话框,直接显示其信息。

续表3-2:

.

. OnClickAdpTree() 消息处理函数 NMHDR*pNMHDR, LRESULT* pResult 当双击选中网卡时,找到选中的网卡,设置list控件,并显示网卡名称、描述等信息。 OnOK() 消息处理函数 OnCancel() 消息处理函数 成员变量 *dev *alldevs errbuf [PCAP_ERRBUF_SIZE]

无 对选中的网卡进行判断,不可以选虚拟网卡也不可不选。 无 关闭对话框 类型 pcap_if_t pcap_if_t char 含义 适配器链表 适配器链表 存储错误信息的字符串 类:CMainFrame类:CAdpterDlgOnInitDialog()对话框设置,并显示适配器列表alldevs=NULL;dev=NULL;点击:适配器->选择适配器OnClickAdpTree()双击适配器,List列表显示详细信息OnAdpChoose()选择适配器aLldevs=adp.alldevs、dev=adp.devOnOK()点击按钮,绑定网卡

图3-8 CAdpterDlg类中函数调用流程图

CCapPackView,视图类,主要功能是实现接收从类MainFrm传递过来的消息和报文,将数据包的头部及数据包的数据内容分别保存在CArray数组中,然后调用报文类IPGram、 ARPGram、RARPGram中的函数,将数据包简要信息显示于界面。表3-3为

.

.

CCapPackView的成员函数及成员变量的说明。图3-9为其类中方法调用流程图。

表3-3 CCapPackView类说明

CCapPackView类 父类 成员函数 OnInitialUpdate() 公有 OnPacketReceive() 消息处理函数 OnItemchanged() 消息处理函数 pcap_pkthdr*pkt_header, constu_char*pkt_data NMHDR* pNMHDR, 当点击列表中某行信息,将向ProTreeView发送消息,并传递报文信息。 成员变量 index totalmem time delta

类:CCapPackViewCListView类 参数 无 功能 设置CapPackView视图的视图风格,设置其列信息。 显示所有抓到的包的简要信息 LRESULT* pResult 类型 int int int int 含义 序号 收到的报文占用总字节数 流逝的秒数 一秒内收到的字节数 OnInitialUpdate()视图设置OnPacketReceive()显示所有抓到的包的简要信息OnItemchanged()向ProTreeView发送消息,并传递报文信息

.

.

图3-9 CCapPackView类中函数调用流程图

CProTreeView,视图类,主要功能是接收来自于CapPackView的消息,调用消息处理函数OnPacketSelect(),在显示数据前清空列表及捕获的数据包。对传递过来的报文头部和内容进行分析,调用报文类IPGram、 ARPGram、RARPGram中的函数将具体信息显示于树形列表中。表3-4为CProTreeView的成员函数及成员变量的说明。

表3-4 CProTreeView类说明

CProTreeView类 父类 成员函数 OnInitialUpdate() OnPacketSelect() 消息处理函数 pcap_pkthdr*pkt_header, constu_char*pkt_data (报文头部和内容指针) OnClick() NMHDR* pNMHDR, 无 无 CTreeView类 参数 功能 设置ProTreeView视图的视图风格,解析树。 以树形结构显示选中的包的具体信息。 LRESULT* pResult 成员变量 *ip *ether *arp *rarp

类型 IPGram EtherHead int int 含义 指向IP报文的指针 指向以太帧的指针 指向ARP报文的指针 指向RARP报文的指针 3.5程序设计

对菜单中的按钮项分别建立类向导、增加函数,如“选择适配器”的消息映射关系为ON_COMMAND(ID_ADP_CHOOSE, OnAdpChoose),“开始抓包”的消息映射关系为ON_COMMAND(ID_FILE_START, OnFileStart);“停止抓包”的消息映射关系为ON_COMMAND(ID_FILE_STOP, OnFileStop)以及菜单项是否禁用的菜单项的状态的响应消息映射关系。这些都是在CMainFrame类里面定义或声明的,CMainFrame作为一个主控类,当操作时,其调用其他的对话框类、视图类,然后再调用报文类。

.

.

网卡的绑定,为ID_ADP_CHOOSE选择适配器建立类向导,新建函数:OnAdpChoose(),打开适配器对话框,并对网卡链表进行传递。具体代码如下:

void CMainFrame::OnAdpChoose()

{ CAdpterDlg adp;//为适配器对话框初始化值

adp.mainFrm=this;

adp.alldevs=this->alldevs; adp.dev=this->dev;

if(adp.DoModal()==IDOK){//将适配器信息返回 this->alldevs=adp.alldevs; this->dev=adp.dev; }}

适配器对话框的数据初始化:在类向导中为类CAdpterDlg添加WM_INITDIALOG消息,并添加默认函数:OnInitDialog,点击“Edit Code”对函数进行编辑。Pcap 提供cap_findAlldevs() 这个函数来实现些功能,返回一个pcap_if 结构的链表,链表的每项内容都含有全面的网卡信息,网卡名称和网卡描述,特别是pcap_findalldevs()这个函数返回的每个pcap_if 结构体都同包含一个pcap_addr 结构的列表,它包含:一个地址列表,一个掩码列表,一个广播地址列表和一个目的地址列表。

为Tree Contrl 建立类向导,增加OnClickAdpTree(),实现双击网卡,在List Contrl中显示网卡具体信息,要注意的是显示网卡详细信息时,调用DeleteAllItems()删除原来内容。

捕获包并显示数据包的简要信息规划捕获包和分析数据包的界面,我准备将视图分为左右两部分,左边为一个ListView,右边为一个TreeView。所以新建两个类CapPackView(继承CListView)、ProTreeView(继承CTreeView)。CapPackView负责显示所有抓到的包的简要信息,ProTreeView负责显示选中的包的具体信息。

在主窗口按下开始抓包按钮时,启动捕获包线程ReceivePacket,调用pcap_open_live(dev->name,65536,1,1000,errbuf))打开网卡,在这里第三个参数设置为1代表将适配器设置为混杂模式,捕获所有流经此适配器的数据包。网卡一旦打开,就可以调用pcap_loop()进行数据的捕获。每次捕获到数据包时,libpcap都会自动调用回调函数pcap_handle(),在回调函数里,PostMessage()向CapPackView发送消息,通知CapPackView处理收到的包。在这里,使用的是自定义消息来实现的,即首先自定义消息#define WM_MESSAGE_PACKET_RECEIVE WM_USER+1,类CCapPackView头文件

.

.

中声明消息的数据包处理函数:afx_msg void OnPacketReceive(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)。

CapPackView收到消息,调用OnPacketReceive()将将所捕获包的内容复制下来,并保存到CArray数组中,然后对包的类型进行判断,当为IP数据包时,调用类IPGram中的函数GetSrcAddr()(获取IP数据包的源IP地址),GetDestAddr()(获取IP数据包的目的IP地址),ip.GetService()(得到IP数据包的协议类型),将这些信息及数据包的长度等显示到界面。类似的,如果数据包为ARP或RARP类型,则相应的调用类ARPGram、RARPGram中的GetSrcPrtAddr()、GetDestPrtAddr(),GetSrcPrtAddr()、GetDestPrtAddr()等函数,并将信息逐行显示于界面。

选中CapPackView中的某条信息,将数据包的具体信息显示于ProTreeView中。定义响应操作的消息#define WM_MESSAGE_PACKET_SELECT WM_USER+2,在类CProTreeView头文件中声明消息的处理函数:afx_msg void OnPacketSelect(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);在类CCpPackView中,调用PostMessage()通知ProTreeView刷新为新选中的报文内容。

类CProTreeView接收到消息后,调用OnPacketSelect(),对数据包进行分析,首先解析以太帧,调用类EtherHead中的函数GetMacDestAddr()(获取目的MAC地址)、GetMacSrcAddr()(获取源MAC地址)。然后根据数据包类型的不同,调用IP数据包、ARP数据包、RARP数据包处理类IPGram、 ARPGram、RARPGram中的函数,逐行插入数据包的具体信息。

需要停止抓包时,点击菜单项或图标按钮停止抓包。只需要添加消息处理函数OnFileStop(),设置一下开始抓包或停止抓包状态。

完善程序。对一些可能出现的情况进行错误处理,如选择网卡时,抓包是时按钮状态是否禁用等等。到此,基本上完成了程序所需要的所有功能。[8]

图3-10 类向导设置变量

3.6程序使用说明

.

.

点击菜单栏“适配器”下的“选择适配器”菜单按钮,(或工具栏中的适配器选项)进行适配器的绑定,如图3-11。

图3-11 选择适配器菜单项

双击选中检测的网卡,下方出现该网卡信息,按OK即完成网卡绑定。(不能选虚拟网卡,即 没有IP地址的网卡)。如图3-12。

图3-12 网卡绑定

菜单文件开始抓包(或工具栏)按下,开始抓包。

然后程序开始抓包,每一行为一个报文,左边视图中简要显示了每个报文的,源、目的IP地址,长度,类型信息。如图3-13所示。

.

.

图3-13 数据包简要信息

选中一报文,则出现下图3-14。

图3-14 具体信息显示

.

.

TCP、UDP、ICMP报文解析树展示,如图3-15所示。

图3-15 IP报文具体信息显示

ARP或RARP报文解析树,如图3-16所示。

图3-16 ARP数据包具体信息显示

4出现的问题与解决方法

在用Ethereal捕获数据包时,没有选择我的IP(10.10.23.226)进行数据包捕获的按钮,导致一直没有捕获到任何的数据包(如图4-1)。这是当然的,因为没有选择针对那个IP进行捕获,根本没有源IP,当然没有数据包,这使我的设计刚开始就频频出错。后来查阅资料时,发了这一个错误,改正后立即可以捕获数据包。所发生的错误如图4-2。

.

.

.

图4-1数据包捕获窗口

图4-2出现的提示错误信息

.

5结束语

经过两周的课程设计,刚开始时还认为两周时间还是很长,有足够的时间完成这个设计,想不到一眨眼间,两周的时间就这样匆匆过去了。现在感觉到时间过得真快,从一开始对Ethereal这个抓包软件没有任何基础的,现在已能对这个软件所捕获的数据包进行简单的分析,以及怎么样设置这个软件的参数。

在用Visual C++编程的这一步中,实在花了我的不少时间,这个我认为是在我这个设计中最难的一步,虽然在网上能找到相关程序,但所找到的那些程序都基本上有一两处错误,而对于我这个只有一点Visual C++基础的来说无疑是一个天大的麻烦。但是,经过这两周的努力,还是能改正了这些错误,而且在同学的帮助下,终于把这个程序给做出来了。经过这一次的设计,这对以后的工作需要提供了很大的帮助。

最后,我得感谢一下在这次课程设计中帮助过我的同学,还有在设计过程中给老师带来了诸多麻烦,很感谢您这么细心的为我讲导。我想,如果这次课程我不可能按时完成。这是我的第一次课程设计 ,其中许多不足,还请老师给与批平、指正。

.

.

参考文献

[1] http://baike.baidu.com/view/69012.htm?fr=ala0_1

[2]Craig Zacker.《TCP/IP网络管理》.北京:中国水利水电出版社,1998.9 [3]谢希仁.《计算机网络》.北京:电子工业出版社,2008.1

[4]黄筱燕.《基于Ethereal的网络协议分析》. 热带农业工程第33卷第1期 [5] http://baike.baidu.com/view/739888.html

[6] http://baike.baidu.com/view/6923.htm?fr=ala0_1

[7]周霭如、林伟健.《C++程序设计基础》.北京:电子工业出版社,2006.3 [8]张青.《C#编程思想与实践》.北京:冶金工业出版社,2002.8

附录:

.

.

附录1网卡的绑定

void CMainFrame::OnAdpChoose()

{ CAdpterDlg adp;//为适配器对话框初始化值

adp.mainFrm=this;

adp.alldevs=this->alldevs; adp.dev=this->dev;

if(adp.DoModal()==IDOK){//将适配器信息返回 this->alldevs=adp.alldevs; this->dev=adp.dev;

}}

附录2报文类

IPGram:IP报文 class IPGram

.

{

int version; //IP版本

int IHL; //IP报文头长,包含多少个32位 int servicetype; //服务类型 int precedence; //优先级 bool delay;

//延迟

bool throughtput; //吞吐量 bool reliability; //可靠性

unsigned int totallen; //IP报文总长 bool DF; //是否分段,为1表示没有分段 bool MF; //是否有进一步分段,为1表示有 int fragoffset; //偏移量 int TTL; //生命期time to live int protocol; /协议:TCP,UDP,ICMP unsigned int checksum; //校验和 long srcaddr; //源IP地址 long destaddr;

//目的IP地址

.

int datalen; //数据长度 unsigned char *data; //数据内容

IPGram();//构造函数

IPGram(const unsigned char* buf,int buflen);//重构函数 virtual ~IPGram();//析构函数

CString GetService();//获取IP数据包的协议类型 void GetDestAddr(char *str);//获取目的IP地址 CString GetDestAddr();//获取目的IP地址 void GetSrcAddr(char *str);//获取源IP地址 CString GetSrcAddr();//获取源IP地址 };

ARPGram:ARP报文 RARPGram:RARP报文

class ARPGram &class RARPGram {

int hdwaddrtype; //硬件地址类型 int prtaddrtype; //协议地址类型 int hdwaddrlen; //硬件地址长度 int prtaddrlen; //协议地址长度 int operation;

//操作类型

BYTE srchdwaddr[6]; //源硬件地址 int srcprtaddr; //源协议地址 BYTE desthdwaddr[6]; //目的硬件地址 int destprtaddr; //目的协议地址

ARPGram();//构造函数

.

ARPGram(const unsigned char *buf,unsigned int buflen);//重构函数 virtual ~ARPGram();//析构函数

CString GetSrcHdwAddr();//ARP/RARP包发送方MAC CString GetSrcPrtAddr();//ARP/RARP包发送方IP

.

CString GetDestHdwAddr();//ARP/RARP包接收方MAC CString GetDestPrtAddr();//ARP/RARP包接收方IP };

EtherHead:以太帧头部

EtherHead();//

.

class EtherHead { int srcaddr[6];

// 源硬件地址

int destaddr[6]; //目的硬件地址

int type; //承载的网络层协议类型:IP,ARP,RARP

构造函数 EtherHead(const unsigned char *buf,int buflen);//重构函数 void GetMacSrcAddr(char *str);//数据包源MAC地址,不返回 CString GetMacSrcAddr();//数据包源MAC地址,返回字符串 void GetMacDestAddr(char *str);// 数据包目的MAC地址,不返回 CString GetMacDestAddr();//数据包目的MAC地址,返回字符串 CString GetType();//获取数据包类型:IP、ARP、RARP virtual ~EtherHead();//析构函数

};

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- efsc.cn 版权所有 赣ICP备2024042792号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务