首页 > 技术文章 > C# 使用SharpPcap读写Pcap包

zhangjd 2020-07-15 15:48 原文

问题描述:

        最近公司新开发一个项目,需要读取pcap包信息,然后去分析。这个也是走了不少弯路,以前也没处理过这么底层的东西,网上能找到的例子也有限,最后用了SharpPcap这个工具,基本可以满足需要,这个工具读取的信息很全,我就不粘贴那么细了,具体的取值类似。

这里用控制台写两个例子做个示范:

1、pacp包信息读取,如果需要更多的值,建议可以进去断点看看,这里只是写个示范。

       public static void Main(string[] args)
        {
            Console.WriteLine("Start!");
            string filePath = @"D:\123.pcap";
            var device = new SharpPcap.LibPcap.CaptureFileReaderDevice(filePath);
            device.Open();
            while (device.GetNextPacket(out var packet) > 0)
            {
                var sourceAddr = string.Empty;
                var destAddr = string.Empty;
                var protocol = string.Empty;
                int sourcePort = 0;
                int destPort = 0;
                int ipDf = 0;//是否分片
                int ipMf = 0;//是否最后一个分片
                long totalLength = 0;//总长度
                string data16 = string.Empty;//字节转为16进制字符串
                if (packet.LinkLayerType != LinkLayers.Ethernet)
                {
                    continue;
                }
                var packetLength = packet.Data.Length;
                var ethPacket = Packet.ParsePacket(packet.LinkLayerType, packet.Data) as EthernetPacket;
                var ipPacket = ethPacket.Extract<IPPacket>();
                if (ipPacket == null)
                {
                    continue;
                }
                destAddr = ipPacket.DestinationAddress.ToString();
                sourceAddr = ipPacket.SourceAddress.ToString();
                protocol = ipPacket.Protocol.ToString();
                if (ethPacket.Type == PacketDotNet.EthernetType.IPv4)
                {
                    var fragmentFlags = ((PacketDotNet.IPv4Packet)ipPacket).FragmentFlags;
                    ipDf = (ushort)fragmentFlags >> 6 & 0x01;
                    ipMf = (ushort)fragmentFlags >> 7 & 0x01;
                    var data = ((PacketDotNet.IPv4Packet)ipPacket).PayloadPacket?.PayloadData;
                    data16 = BytArrayToHexString(data);
                    totalLength = ((PacketDotNet.IPv4Packet)ipPacket).TotalLength;
                }
                else if (ethPacket.Type == PacketDotNet.EthernetType.IPv6)
                {
                    var data = ((PacketDotNet.IPv6Packet)ipPacket).PayloadPacket.PayloadData;
                    data16 = BytArrayToHexString(data);
                    totalLength = ((PacketDotNet.IPv6Packet)ipPacket).TotalLength;
                }
                if (protocol == "Tcp")
                {
                    sourcePort = ((PacketDotNet.TcpPacket)ipPacket.PayloadPacket).SourcePort;
                    destPort = ((PacketDotNet.TcpPacket)ipPacket.PayloadPacket).DestinationPort;
                }
                else if (protocol == "Udp")
                {
                    sourcePort = ((PacketDotNet.UdpPacket)ipPacket.PayloadPacket).SourcePort;
                    destPort = ((PacketDotNet.UdpPacket)ipPacket.PayloadPacket).DestinationPort;
                }
                Console.WriteLine($"sourceAddr:{sourceAddr}, sourcePort:{sourcePort}, destAddr:{destAddr}, destPort:{destPort},protocol:{protocol}");
            }
            device.Close();
            Console.WriteLine("End!");
        }

        public static string BytArrayToHexString(byte[] data)//16进制转换
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (var item in data)
            {
                sb.Append(Convert.ToString(item, 16).PadLeft(2, '0'));
            }
            return sb.ToString().ToUpper();
        }

 

2、从pcap包中筛选信息,重新写数据包,这里实例演示写TCP的包,其余类型的一律过滤掉。(output.pcap找一个正常包就行,写的时候会覆盖的)

        public static void Main(string[] args)
        {
            Console.WriteLine("Start");
            var device = new SharpPcap.LibPcap.CaptureFileReaderDevice(@"D:\123.pcap");
            var deviceOutput = new SharpPcap.LibPcap.CaptureFileWriterDevice(@"D:\output.pcap");
            device.Open();
            deviceOutput.Open();
            while (device.GetNextPacket(out var packet) > 0)
            {
                if (packet.LinkLayerType != LinkLayers.Ethernet)
                {
                    continue;
                }
                var ethPacket = Packet.ParsePacket(packet.LinkLayerType, packet.Data) as EthernetPacket;
                var ipPacket = ethPacket.Extract<IPPacket>();
                if (ipPacket == null)
                {
                    continue;
                }
                if (ipPacket.Protocol == PacketDotNet.ProtocolType.Tcp)
                {
                    deviceOutput.Write(packet);
                }
                Console.WriteLine($"SrcMac:{ethPacket.SourceHardwareAddress}, DstMac:{ethPacket.DestinationHardwareAddress}, SrcIP:{ipPacket.SourceAddress}, DstIP:{ipPacket.DestinationAddress}");

                //再往上各层的分析以此类推
            }
            device.Close();
            deviceOutput.Close();
            Console.WriteLine("End!");
            Console.ReadLine();
        }

  

  

 

推荐阅读