問題描述:
最近公司新開發一個項目,需要讀取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(); }