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