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