C# 使用SharpPcap读写Pcap包
问题描述:
最近公司新开发一个项目,需要读取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(); }