网络攻击与防范实验报告(共23页).doc
精选优质文档-倾情为你奉上网络攻击与防范实验报告姓名:_ _ 学号:_ _ 所在班级: 实验名称: 编写自己的网络嗅探器 实验日期: 2014 年 10 月 22 日指导老师: 张玉清、宋 杨 实验评分: 验收评语: 实验目的:通过开发基于WinPcap的嗅探器,掌握嗅探器的工作原理,熟悉WinPcap的使用,掌握基于WinPcap网络嗅探器的开发过程。实验内容:开发出一个任意平台上的Sniffer(嗅探器)工具,能显示所捕获的局域网数据包并能做相应的分析和统计。主要内容如下: 列出监测主机的所有网卡,选择一个网卡,设置为混杂模式进行监听。 捕获所有流经网卡的数据包,并利用WinPcap函数库设置过滤规则。 分析捕获到的数据包的包头和数据,按照各种协议的格式进行格式化显示。 将所开发工具的捕获和分析结果与常用的Sniffer进行比较,完善程序代码。 实验环境:Ø 硬件环境:² 处理器:Intel(R) Core(TM) i5-3337U CPU 1.80GHz 1.80GHz² 内存:6.00G ² 硬盘:600G ² 网卡:Intel(R) Centrino(R) Wireless-N 2230 / Realtek PCIe FE 系列控制器 ² 网速:约200KB/s Ø 软件环境:² 操作系统: Windows 8.1 x64位操作系统² 开发工具:Visual Studio 2013² 开发语言:C#实验设计:SharpPcap 是一个.NET 环境下的网络包捕获框架,是基于WinPcap 库开发。提供了捕获、注入、分析和构建的功能,适用于C# 和VB NET开发语言。本实验利用SharpPcap提供的这些网络接口获取到底层的网卡信息及其数据包,并且支持捕获前过滤条件和捕获后过滤条件的设定。再根据TCP/IP协议栈的结构capturedPacket.Extract(typeof(ProtocolPacket)和PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data)方法依次在数据链路层、网络层、数据传输层和应用层,分别进行数据包的分拆与解析,获取相应协议层的数据信息,并根据应用程序的端口信息找出其对应的数据包,例如Microsoft-SQL-Server、MySQL、Telnet、QQ、Tomcat等等。实验还对几个最常用的协议,如ARP、IP、ICMP、TCP、UDP等协议的数据包数量进行统计,并用柱状图的形式展现给用户。最后,还从网络层、传输层、应用层三个层次对数据包进行分类,计算它们的百分比,以饼图的形式展现。1、界面设计:图 1 主窗口设计视图本系统主窗口主要分为9个部分。第一部分:菜单菜单栏总共有三项,包括“文件”、“查看”、“帮助”。“文件”菜单项包含常规的几个子菜单:“打开”“保存”“另存为”“退出”;“查看”包括“柱状图”和“饼图”两个子菜单;“帮助”菜单包括“使用帮助”和“关于MySniffer”,下面介绍各个子菜单的功能。 打开:打开Pcap文件,从文件中读取数据包。 保存:将当前捕获的流量包保存到用户选择的位置。 另存为:暂时作用与“保存”相同。 退出:退出系统。 柱状图:如图4所示,以柱状图的形式显示捕获到的数据包,方便用户直观的看到数据包的数量情况,可以对ARP、IP、ICMP、TCP、UDP、HTTP、DNS这几种协议的数据包的个数进行比较。 饼图:如图5所示,以饼图的形式显示捕获到的数据包在不同协议层的分类情况,包括,网络层、传输层和应用层,饼图的左侧图例上显示了每种数据包在该协议层所占的比例,主要的饼图部分更能直观的反应比例关系。最后一个应用层,由于应用的种类实在太多,因此这里只统计了常见的14种应用,详见图5中的图例。 使用帮助:弹出使用帮助对话框,目前内容只是告诉捕获前过滤条件如何设置,还没有加上软件的使用说明,有待完善。如图6。 关于MySniffer:弹出版本信息对话框,如图7所示。图 2 打开文件选项图 3 保存流量包到文件第二部分:选择网卡选择网卡是个下拉菜单,在窗口初始化的时候对下拉菜单进行初始化,将获得的网卡列表加入下拉菜单,用户可以通过点击想要打开的网卡进行网卡的选择第三部分: 捕获前过滤条件设置捕获前过滤条件,该过滤条件由Winpcap规定,在上面的使用帮助对话框中可以得到提示。第四部分:开始抓包和停止抓包按钮点击开始抓包,选中的网卡被打开,开始捕获数据包,此时开始抓包按钮和捕获前过滤文本框变成不可用状态,停止抓包按钮从刚开始的不可用变成可用。如果没有选择网卡将给出提示框。第五部分:捕获后过滤条件设置捕获后过滤条件,这里也做成了下拉菜单的形式,有20种选项,包括ARP、IP、ICMP、TCP、UDP等等,当用户点击过滤按钮的时候,下面的数据包列表框中的内容就会发生改变。第六部分:封包总览封包总览包括时序号、时间、源地址、目的地址、协议、长度这六项。第七部:封包内容封包内容以树状图的形式展示,对数据包进行数据链路层、网络层、传输层、应用层四个层次的展开,最后除去所有的包头得到最终的有用数据。用户可以根据需要展开和折叠内容。 第八部分:十六进制码以及对应的ASCII码将数据包的内容转化成ASCII码显示。第九部分:统计已经抓到的数据包的个数。图 4 部分数据包统计柱状图图 5 各协议层数据包统计饼图图 6 使用帮助对话框图 7 关于对话框2、工作流程及算法设计:本系统中的工作流程主要网络数据包的捕获、数据包的接收,以及数据包的分析处理这三个部分。其中数据包的捕获又可以分为两种,一种是用网卡直接进行数据包的捕获,具体流程如图8所示;另一种方式是从pcap文件中读取数据包,然后进行分析,当用户点击文件菜单中的打开按钮时,创建一个虚拟设备,从文件中读取数据包的信息到内存中,除了利用的是虚拟设备这个跟第一种方式不同以外,对数据包的处理方法都是一样的。图 8 网络数据捕获流程图 数据包的接收也就是device_OnPacketArrival这个事件的实现。在这个啥时间中,我们对捕获到的数据包进行分析,找到里面包含的数据包类型,比如一个数据包是以太网数据包,去掉以太网包头以后里面可能是一个IP数据包,再去掉IP包头以后里面是一个TCP数据包,然后根据数据包的源端口和目的端口我们可以大概的判断这是哪个应用的数据包,像FTP的端口是20和21,Telnet的端口是23等等。这样,我们就可以将数据包添加到相应的packet队列,具体流程如图9所示。图 9 网络数据捕获流程图在捕获到数据以后,开启后台线程对packet队列进行处理和显示,将packet中的基本信息,如序列、捕获到的时间、源地址、目的地址、使用的协议、数据包的长度等等,然后将其显示在ListView中,具体流程如图10所示。在用户点击ListView中的一行的时候调用包解析函数对数据包进行分析,得到各个协议层的源地址、目的地址、数据包长度等信息,以及最终内部的有用数据,显示在下面的两个方框中,一个以树状图的形式显示,另一个显示十六进制内容和对应的ASCII码。图 10 数据包列表显示流程图详细过程:1、数据结构:本系统中定义的数据结构如下:(1)网络设备public CaptureDeviceList devices; /网卡列表private ICaptureDevice _device = null; /捕获网卡private CaptureFileWriterDevice captureFileWriter = null; /读取pcap文件的虚拟网络设备(2)数据包队列 捕获数据存放在PacketQueue队列中,这个队列中的每个元素又是一个队列,第一个队列用来存放所有的数据包,以后的每个队列代表不同类型的数据包,如网络层的数据包有ARP、IP和ICMP,传输层数据包有TCP和UDP,以及一系列的应用层的数据包。这里举了几个例子:private List<List<RawCapture>> PacketQueue = new List<List<RawCapture>>(); private List<RawCapture> AllPacketQ = new List<RawCapture>();private List<RawCapture> ARPPacketQ = new List<RawCapture>();private List<RawCapture> IpPacketQ = new List<RawCapture>();private List<RawCapture> ICMPPacketQ = new List<RawCapture>(); (3)其他private int QueueNum = 0; /读取的队列号private Thread _Backgroundthread; /后台处理列表数据放入listviewprivate object QueueLock = new object(); /防止数据入队和读取同时进行发生错误2、获取网络设备devices = CaptureDeviceList.Instance; /获取网络设备foreach (var dev in devices) boBox1.Items.Add(dev.Description); /将网卡信息显示到选择网卡的下拉菜单中3、打开选中的网卡,获取数据包信息private void startCaptureButton_Click(object sender, EventArgs e) if (boBox1.SelectedIndex >= 0) try_device = devicesboBox1.SelectedIndex;_device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);/设置接收数据包的事件_device.Open();/打开网络设备_device.Filter=pre_filter_textBox.Text;/设置捕获前过滤的条件captureFileWriter=new CaptureFileWriterDevice("temp.pcap");/创建一个写pcap临时文件的captureFileWriter,每当捕获到一个数据包的时候就保存到临时文件temp.pcap中。for(inti=0;i<20;i+)PacketQueuei.Clear();_device.StartCapture();tryif(_Backgroundthread.IsAlive)_Backgroundthread.Abort(); catch ThreadStartthread=newThreadStart(Backgroundprocess);_Backgroundthread=newThread(thread);_Backgroundthread.Start();/开启后台线程,将捕获到的数据包显示到listview中pre_filter_textBox.ReadOnly=true;/设置过滤选项和按钮的可用性stopCaptureButton.Enabled=true;startCaptureButton.Enabled=false;catch(Exceptionex) MessageBox.Show("过滤规则错误!"+ex.Message,"警告!"); else MessageBox.Show("请选择网卡!","提示");4、打开已捕获的流量包文件private void Open_ToolStripMenuItem_Click(object sender, EventArgs e) OpenFileDialog openDialog = new OpenFileDialog(); openDialog.Title = "打开流量包" openDialog.Filter = "pcap(*.pcap)|*.pcap"if(openDialog.ShowDialog() = DialogResult.OK)CaptureFileReaderDevice captureFileReader = new CaptureFileReaderDevice(openDialog.FileName);/创建读取流量包的虚拟设备captureFileReader.OnPacketArrival += new PacketArrivalEventHandler(onReadFile);/设置接收数据包的事件captureFileReader.StartCapture(); try if (_Backgroundthread.IsAlive) _Backgroundthread.Abort(); catch ThreadStart thread = new ThreadStart(Backgroundprocess); _Backgroundthread = new Thread(thread); _Backgroundthread.Start(); /开启后台线程 private void onCaptureStopped(object sender, CaptureStoppedEventStatus status) / MessageBox.Show("文件读取成功!"); 5、OnPacketArrival事件OnPacketArrival事件用于接收捕获到的数据包,将数据包进行分类保存private void device_OnPacketArrival(object sender, CaptureEventArgs e) /static captureFileWriter.Write(e.Packet);/将捕获的数据包保存到临时文件 onReadFile(sender, e);/分析数据包,将数据包进行分类保存 private void onReadFile(object sender,CaptureEventArgs e) /分析数据包,将数据包进行分类保存 var packet = PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); if (packet is PacketDotNet.EthernetPacket) lock (QueueLock) AllPacketQ.Add(e.Packet); /检查是否包含ARP数据包,如果有则加到ARPPacketQ队列中 var eth = (PacketDotNet.EthernetPacket)packet); if (packet.PayloadPacket is PacketDotNet.ARPPacket) lock (QueueLock) ARPPacketQ.Add(e.Packet); /检查是否包含IP数据包,如果有则加到IpPacketQ队列中 var ipPacket = packet.Extract(typeof(IpPacket); if (ipPacket != null) lock (QueueLock) IpPacketQ.Add(e.Packet); var tcpPacket = PacketDotNet.TcpPacket.GetEncapsulated(packet); if (tcpPacket != null) lock (QueueLock) TcpPacketQ.Add(e.Packet); if (tcpPacket.SourcePort = 20 | tcpPacket.DestinationPort = 20) lock (QueueLock) FtpdPacketQ.Add(e.Packet); var udpPacket = PacketDotNet.UdpPacket.GetEncapsulated(packet); if (udpPacket != null) lock (QueueLock) UdpPacketQ.Add(e.Packet); if (udpPacket.SourcePort = 53 | udpPacket.DestinationPort = 53) lock (QueueLock) DNSPacketQ.Add(e.Packet); if (udpPacket.SourcePort = 4000 | udpPacket.DestinationPort = 4000 | udpPacket.SourcePort = 4001 | udpPacket.DestinationPort = 4001) lock (QueueLock) QQPacketQ.Add(e.Packet); var icmpv4Packet = packet.Extract(typeof(ICMPv4Packet); var icmpv6Packet = packet.Extract(typeof(ICMPv6Packet); if (icmpv4Packet != null | icmpv6Packet != null) lock (QueueLock) ICMPPacketQ.Add(e.Packet); 6、Backgroundprocess后台进程Backgroundprocess后台用于进程添加表格数据,分析出序号,事件,原地址和,目的地址,协议的种类和数据包的长度,最后统计出捕获到的各类数据包的数量。rivate void Backgroundprocess( ) Control.CheckForIllegalCrossThreadCalls = false;/跨线程操作 int _count = 0; this.listView1.GridLines = true; this.listView1.Clear(); this.listView1.Columns.Add("序号", 60, HorizontalAlignment.Left); this.listView1.Columns.Add("时间", 120, HorizontalAlignment.Left); this.listView1.Columns.Add("源地址", 120, HorizontalAlignment.Left); this.listView1.Columns.Add("目的地址", 120, HorizontalAlignment.Left); this.listView1.Columns.Add("协议", 60, HorizontalAlignment.Left); this.listView1.Columns.Add("长度", 80, HorizontalAlignment.Left); while (true) if (_count < PacketQueueQueueNum.Count) RawCapture Addpacket; lock (QueueLock) Addpacket = PacketQueueQueueNum_count; _count+; ListViewItem item = new ListViewItem(); var time = Addpacket.Timeval.Date.ToLocalTime(); item.SubItems0.Text = _count.ToString(); item.SubItems.Add(time.TimeOfDay.ToString(); string souce = "", destination = "", type = ""var packet = PacketDotNet.Packet.ParsePacket(Addpacket.LinkLayerType, Addpacket.Data); if (packet is PacketDotNet.EthernetPacket) var eth = (PacketDotNet.EthernetPacket)packet); souce = eth.SourceHwAddress.ToString(); destination = eth.DestinationHwAddress.ToString(); if (destination = "ffffffffffff" | destination = "FFFFFFFFFFFF") destination = "广播地址" type = eth.Type.ToString(); var ipPacket = PacketDotNet.IpPacket.GetEncapsulated(packet); if (ipPacket != null) souce = ipPacket.SourceAddress.ToString(); if (ipPacket.SourceAddress.IsIPv6LinkLocal) souce += "IPv6链接本地地址" if (ipPacket.SourceAddress.IsIPv6Multicast) souce += "IPv6多路广播全局地址" if (ipPacket.SourceAddress.IsIPv6SiteLocal) souce += "IPv6站点本地地址" if (ipPacket.SourceAddress.IsIPv6Teredo) souce += "IPv6 Teredo地址" destination = ipPacket.DestinationAddress.ToString(); if (ipPacket.SourceAddress.IsIPv6LinkLocal) destination = "IPv6链接本地地址" if (ipPacket.DestinationAddress.IsIPv6Multicast) destination = "IPv6多路广播全局地址" if (ipPacket.DestinationAddress.IsIPv6SiteLocal) destination = "IPv6站点本地地址" if (ipPacket.DestinationAddress.IsIPv6Teredo) destination = "IPv6 Teredo地址" type = ipPacket.Protocol.ToString(); var tcpPacket = PacketDotNet.TcpPacket.GetEncapsulated(packet); if (tcpPacket != null) if (tcpPacket.DestinationPort = 80 | tcpPacket.SourcePort = 80) type = "HTTP" else if (tcpPacket.DestinationPort = 443) type = "HTTPS" else if (tcpPacket.DestinationPort = 21) type = "FTP" else type = "tcp" + ":" + tcpPacket.SourcePort.ToString() + " to " + tcpPacket.DestinationPort.ToString(); var udpPacket = PacketDotNet.UdpPacket.GetEncapsulated(packet); if (udpPacket != null) if (udpPacket.DestinationPort = 53) type = "DNS" else type = "udp" + ":" + udpPacket.DestinationPort.ToString() + " to " + udpPacket.DestinationPort.ToString();