using Newtonsoft.Json; using PcapDotNet.Core; using System.IO; using System; using System.Linq; using System.Buffers.Binary; using System.Runtime.InteropServices; using AscNet.Common.Util; using MessagePack; using System.Collections.Generic; using PcapDotNet.Packets.IpV4; namespace AscNet.PcapParser { class PcapParser { private static readonly MessagePackSerializerOptions lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4Block); private static readonly Dictionary buffer = new Dictionary(); private static readonly MemoryStream memoryStream = new MemoryStream(); private static readonly List packets = new List(); static void Main(string[] args) { // Check command line if (args.Length != 1) { Console.WriteLine("usage: " + Environment.GetCommandLineArgs()[0] + " "); return; } // Create the offline device OfflinePacketDevice selectedDevice = new OfflinePacketDevice(args[0]); // Open the capture file using (PacketCommunicator communicator = selectedDevice.Open(65536, // portion of the packet to capture // 65536 guarantees that the whole packet will be captured on all the link layers PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode 1000)) // read timeout { // Read and dispatch packets until EOF is reached communicator.ReceivePackets(0, DispatcherHandler); } // ProcessPackets(); Console.WriteLine($"Got {packets.Count} packet(s)"); File.WriteAllText("packets.json", JsonConvert.SerializeObject(packets)); } private static void DispatcherHandler(PcapDotNet.Packets.Packet packet) { var payload = packet.Ethernet.IpV4.Tcp.Payload; if (payload.Length < 1) return; byte[] bytes; if (buffer.ContainsKey(packet.Ethernet.IpV4.Source)) { bytes = buffer[packet.Ethernet.IpV4.Source].Concat(payload.ToArray()).ToArray(); } else { bytes = payload.ToArray(); } int readLen = 0; while (true) { if (4 > bytes.Length - readLen) { buffer[packet.Ethernet.IpV4.Source] = bytes.AsSpan(readLen).ToArray(); break; } int len = (int)BinaryPrimitives.ReadUInt32LittleEndian(bytes.AsSpan(readLen)); readLen += Marshal.SizeOf(); if (len > bytes.Length - readLen) { buffer[packet.Ethernet.IpV4.Source] = bytes.AsSpan(readLen - 4).ToArray(); break; } byte[] packetBuffer = new byte[len]; Buffer.BlockCopy(bytes, readLen, packetBuffer, 0, len); readLen += len; Crypto.HaruCrypt.Decrypt(packetBuffer); try { var msgPackPacket = MessagePackSerializer.Deserialize(packetBuffer, lz4Options); var packetObj = new Dictionary { ["No"] = msgPackPacket.No, ["Type"] = msgPackPacket.Type.ToString() }; switch (msgPackPacket.Type) { case Packet.ContentType.Request: var req = MessagePackSerializer.Deserialize(msgPackPacket.Content); packetObj["Content"] = new { req.Id, req.Name, Content = req.Deserialize() }; Console.WriteLine($"{req.Name}, " + JsonConvert.SerializeObject(req.Deserialize())); break; case Packet.ContentType.Response: var rsp = MessagePackSerializer.Deserialize(msgPackPacket.Content); packetObj["Content"] = new { rsp.Id, rsp.Name, Content = rsp.Deserialize() }; Console.WriteLine($"{rsp.Name}, " + JsonConvert.SerializeObject(rsp.Deserialize())); break; case Packet.ContentType.Push: var push = MessagePackSerializer.Deserialize(msgPackPacket.Content); packetObj["Content"] = new { push.Name, Content = push.Deserialize() }; Console.WriteLine($"{push.Name}, " + JsonConvert.SerializeObject(push.Deserialize())); break; case Packet.ContentType.Exception: var ex = MessagePackSerializer.Deserialize(msgPackPacket.Content); packetObj["Content"] = ex; Console.WriteLine(JsonConvert.SerializeObject(ex)); break; default: break; } packets.Add(packetObj); } catch (Exception) { Console.WriteLine("len: " + len + ", pack: " + Convert.ToBase64String(packetBuffer)); byte[] rawBuf = new byte[len + 4]; Buffer.BlockCopy(bytes, (readLen - len - 4), rawBuf, 0, len + 4); Console.WriteLine("Ended abruptly while reading, processing: " + Convert.ToBase64String(rawBuf)); break; } if (readLen >= bytes.Length) { buffer.Remove(packet.Ethernet.IpV4.Source); break; } } // print packet timestamp and packet length /*Console.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + payload.Length); memoryStream.Write(payload.ToArray(), 0, payload.Length);*/ } private static void ProcessPackets() { List packets = new List(); byte[] msBytes = memoryStream.ToArray(); int readLen = 0; while (readLen < msBytes.Length) { int len = BinaryPrimitives.ReadInt32LittleEndian(msBytes.AsSpan(readLen)); readLen += Marshal.SizeOf(); byte[] packetBuffer = new byte[len]; Buffer.BlockCopy(msBytes, readLen, packetBuffer, 0, len); readLen += len; Crypto.HaruCrypt.Decrypt(packetBuffer); try { var packet = MessagePackSerializer.Deserialize(packetBuffer, lz4Options); var packetObj = new Dictionary { ["No"] = packet.No, ["Type"] = packet.Type.ToString() }; switch (packet.Type) { case Packet.ContentType.Request: var req = MessagePackSerializer.Deserialize(packet.Content); packetObj["Content"] = new { req.Id, req.Name, Content = req.Deserialize() }; Console.WriteLine($"{req.Name}, " + JsonConvert.SerializeObject(req.Deserialize())); break; case Packet.ContentType.Response: var rsp = MessagePackSerializer.Deserialize(packet.Content); packetObj["Content"] = new { rsp.Id, rsp.Name, Content = rsp.Deserialize() }; Console.WriteLine($"{rsp.Name}, " + JsonConvert.SerializeObject(rsp.Deserialize())); break; case Packet.ContentType.Push: var push = MessagePackSerializer.Deserialize(packet.Content); packetObj["Content"] = new { push.Name, Content = push.Deserialize() }; Console.WriteLine($"{push.Name}, " + JsonConvert.SerializeObject(push.Deserialize())); break; case Packet.ContentType.Exception: var ex = MessagePackSerializer.Deserialize(packet.Content); packetObj["Content"] = ex; Console.WriteLine(JsonConvert.SerializeObject(ex)); break; default: break; } packets.Add(packetObj); } catch (Exception) { Console.WriteLine("len: " + len + ", pack: " + Convert.ToBase64String(packetBuffer)); byte[] rawBuf = new byte[len + 4]; Buffer.BlockCopy(msBytes, (readLen - len - 4), rawBuf, 0, len + 4); Console.WriteLine("Ended abruptly while reading, processing: " + Convert.ToBase64String(rawBuf)); break; } } } } }