/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out ICMP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { packet = new ICMP(); packet.Type = br.ReadByte(); packet.Code = br.ReadByte(); packet.Checksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.ID = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.Sequence = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.Data = br.ReadBytes(count - 8); return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out ARP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { packet = new ARP(); packet.HType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.PType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.HLen = br.ReadByte(); packet.PLen = br.ReadByte(); packet.Operation = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); if (count < 6 + packet.HLen * 2 + packet.PLen * 2) { packet.SenderHardwareAddress = new byte[packet.HLen]; packet.SenderProtocolAddress = new byte[packet.PLen]; packet.TargetHardwareAddress = new byte[packet.HLen]; packet.TargetProtocolAddress = new byte[packet.PLen]; } else { packet.SenderHardwareAddress = br.ReadBytes(packet.HLen); packet.SenderProtocolAddress = br.ReadBytes(packet.PLen); packet.TargetHardwareAddress = br.ReadBytes(packet.HLen); packet.TargetProtocolAddress = br.ReadBytes(packet.PLen); } return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out EapolKey packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { packet = new EapolKey(); packet.KeyDescriptorType = br.ReadByte(); packet.KeyInformation = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.KeyLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.ReplayCounter = br.ReadBytes(8); packet.Nonce = br.ReadBytes(32); packet.IV = br.ReadBytes(16); packet.RSC = br.ReadBytes(8); packet.ID = br.ReadBytes(8); packet.MIC = br.ReadBytes(16); packet.DataLen = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet.Data = br.ReadBytes((int)(count - br.BaseStream.Position)); return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out SNAP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var organizationCode = br.ReadBytes(3); var etherType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet = null; if (organizationCode[0] == 0 && organizationCode[1] == 0 && organizationCode[2] == 0) { switch (etherType) { case (ushort)EtherTypes.IPv4: { IPv4 payload; if (IPv4.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <IPv4> { Payload = payload }; } } break; case (ushort)EtherTypes.ARP: { ARP payload; if (ARP.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <ARP> { Payload = payload }; } } break; case (ushort)EtherTypes.EAPoLAN: { IEEE802_1x payload; if (IEEE802_1x.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <IEEE802_1x> { Payload = payload }; } } break; } } if (packet == null) { Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload); // This can never fail, so I'm not checking the output packet = new SNAP <Generic> { Payload = payload }; } packet.OrganizationCode = organizationCode; packet.ProtocolID = etherType; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out IPv4 packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var versionAndHeaderLen = br.ReadByte(); var version = versionAndHeaderLen >> 4; var headerLength = versionAndHeaderLen & 0x0F; var differentiatedServices = br.ReadByte(); var totalLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var id = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var flagsAndFragOff = new BitVector32(ByteOrder.NetworkToHostOrder(br.ReadUInt16())); var ttl = br.ReadByte(); var protocol = br.ReadByte(); var headerChecksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var sourceAddress = new IPv4Address(br.ReadBytes(4)); var destAddress = new IPv4Address(br.ReadBytes(4)); if (headerLength == 0 || (headerLength * 32 / 8 > count)) { // Specified header length is larger than available bytes packet = null; return(false); } byte[] optionsAndPadding; if (headerLength * 32 / 8 < br.BaseStream.Position) { optionsAndPadding = br.ReadBytes(headerLength * 32 / 8 - (int)br.BaseStream.Position); } else { optionsAndPadding = Array.Empty <byte>(); } br.BaseStream.Seek(headerLength * 32 / 8, SeekOrigin.Begin); // TODO: Accept option for IgnoreLength int payloadLength; if (true /*IgnoreLength*/) { payloadLength = count - (int)br.BaseStream.Position; } /*else * { * payloadLength = (totalLength - (headerLength * 32 / 8) * }*/ packet = null; switch (protocol) { case (byte)Protocols.UDP: { UDP payload; if (UDP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <UDP> { Payload = payload }; } } break; case (byte)Protocols.ICMP: { ICMP payload; if (ICMP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <ICMP> { Payload = payload }; } } break; case (byte)Protocols.TCP: { TCP payload; if (TCP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <TCP> { Payload = payload }; } } break; } if (packet == null) { Generic payload; Generic.TryParse(buffer, index + (int)br.BaseStream.Position, payloadLength, out payload); // This can never fail, so I'm not checking the output packet = new IPv4 <Generic> { Payload = payload }; } packet.Version = version; packet.HeaderLength = headerLength; packet.DifferentiatedServices = differentiatedServices; packet.TotalLength = totalLength; packet.ID = id; packet.FlagsAndFragOff = flagsAndFragOff; packet.TTL = ttl; packet.Protocol = protocol; packet.HeaderChecksum = headerChecksum; packet.SourceAddress = sourceAddress; packet.DestAddress = destAddress; packet.OptionsAndPadding = optionsAndPadding; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out IEEE802_1x packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var version = br.ReadByte(); var type = br.ReadByte(); var bodyLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var payloadLength = Math.Min(bodyLength, (int)(count - br.BaseStream.Position)); packet = null; switch (type) { case (byte)Types.EAPOL_KEY: { EapolKey payload; if (EapolKey.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IEEE802_1x <EapolKey> { Payload = payload }; } } break; } if (packet == null) { Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload); // This can never fail, so I'm not checking the output packet = new IEEE802_1x <Generic> { Payload = payload }; } packet.Version = version; packet.Type = type; packet.BodyLength = bodyLength; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out TCP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var sourcePort = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var destPort = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var seqNumber = ByteOrder.NetworkToHostOrder(br.ReadUInt32()); var ackNumber = ByteOrder.NetworkToHostOrder(br.ReadUInt32()); var dataOffsetAndReserved = br.ReadByte(); var dataOffset = dataOffsetAndReserved >> 4; var reserved = dataOffsetAndReserved & 0x0F; var flags = new BitVector32(br.ReadByte()); var windowSize = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var checksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var urgentPointer = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); byte[] optionsAndPadding = null; if (dataOffset > 5) { if (br.BaseStream.Position + (dataOffset - 5) * 4 > count) { // throw new ArgumentException("Header specifies more bytes than available"); packet = null; return(false); } optionsAndPadding = br.ReadBytes((dataOffset - 5) * 4); } Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, count - dataOffset * 32 / 8, out payload); // This can never fail, so I'm not checking the output var newPacket = new TCP <Generic>(); newPacket.Payload = payload; packet = newPacket; packet.SourcePort = sourcePort; packet.DestPort = destPort; packet.SeqNumber = seqNumber; packet.AckNumber = ackNumber; packet.DataOffset = dataOffset; packet.Reserved = reserved; packet.Flags = flags; packet.WindowSize = windowSize; packet.Checksum = checksum; packet.UrgentPointer = urgentPointer; packet.OptionsAndPadding = optionsAndPadding ?? Array.Empty <byte>(); return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out IEEE802_11 packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var frameControlVersionTypeAndSubtype = new BitVector32(br.ReadByte()); var frameControlFlags = new BitVector32(br.ReadByte()); var durationID = br.ReadUInt16(); var toDS = frameControlFlags[1]; var fromDS = frameControlFlags[2]; byte[] destination; byte[] source; byte[] bssid; byte[] receiver = null; byte[] transmitter = null; UInt16 sequenceControl; if (!toDS) { destination = br.ReadBytes(6); if (!fromDS) { source = br.ReadBytes(6); bssid = br.ReadBytes(6); } else { bssid = br.ReadBytes(6); source = br.ReadBytes(6); } sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees } else { if (!fromDS) { bssid = br.ReadBytes(6); source = br.ReadBytes(6); destination = br.ReadBytes(6); sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees } else { receiver = br.ReadBytes(6); transmitter = br.ReadBytes(6); bssid = transmitter; //Per airdecap-ng destination = br.ReadBytes(6); sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees source = br.ReadBytes(6); } } var frameType = frameControlVersionTypeAndSubtype[BitVector32.CreateSection(3, BitVector32.CreateSection(3)) ]; var subType = frameControlVersionTypeAndSubtype[ BitVector32.CreateSection(15, BitVector32.CreateSection(15))]; byte[] qosControl = null; if (frameType == (int)FrameTypes.Data && subType == (int)DataSubTypes.QoS) { qosControl = br.ReadBytes(2); } var isProtected = frameControlFlags[64]; byte[] ccmp_WEP_Data = null; if (isProtected) { if (count - br.BaseStream.Position < 4) { packet = null; return(false); } var firstFour = br.ReadBytes(4); if (firstFour[3] == 0) { ccmp_WEP_Data = firstFour; } else { if (count - br.BaseStream.Position < 4) { packet = null; return(false); } ccmp_WEP_Data = new byte[8]; firstFour.CopyTo(ccmp_WEP_Data, 0); br.ReadBytes(4).CopyTo(ccmp_WEP_Data, 4); } } var isWep = isProtected && ccmp_WEP_Data?.Length == 4; if (count - br.BaseStream.Position - (isWep ? 4 : 0) < 0) { packet = null; return(false); } var unsafePayloadLen = count - (int)br.BaseStream.Position - (isWep ? 4 : 0); var safePayloadLen = Math.Max(0, unsafePayloadLen); packet = null; if (frameType == (int)FrameTypes.Data && ((subType & 4) != 1) && !isProtected) { LLC payload; if (LLC.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload)) { packet = new IEEE802_11 <LLC> { Payload = payload }; } } else if (frameType == (int)FrameTypes.Management && subType == (int)ManagementSubTypes.Beacon) { Beacon802_11 payload; if (Beacon802_11.TryParse( buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload)) { packet = new IEEE802_11 <Beacon802_11> { Payload = payload }; } } if (packet == null) { Generic payload; Generic.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload); // This can never fail, so I'm not checking the output packet = new IEEE802_11 <Generic> { Payload = payload }; } br.BaseStream.Seek(packet.Payload.Length(), SeekOrigin.Current); UInt32 wep_ICV = 0; if (isWep) { wep_ICV = ByteOrder.NetworkToHostOrder(br.ReadUInt32()); } packet.FrameControlVersionTypeAndSubtype = frameControlVersionTypeAndSubtype; packet.FrameControlFlags = frameControlFlags; packet.DurationID = durationID; packet.Destination = destination; packet.Source = source; packet.BSSID = bssid; packet.SequenceControl = sequenceControl; packet.Receiver = receiver; packet.Transmitter = transmitter; packet.QosControl = qosControl; packet.CCMP_WEP_Data = ccmp_WEP_Data; packet.WEP_ICV = wep_ICV; if (br.BaseStream.Position == count - 4) { packet.FrameCheckSequence = br.ReadUInt32(); } return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out UDP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var sourcePort = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var destPort = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var totalLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var checksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet = null; if (destPort == 53) { if (DNSQuery.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out DNSQuery payload)) { packet = new UDP <DNSQuery> { Payload = payload }; } } else if (sourcePort == 53) { if (DNSReply.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out DNSReply payload)) { packet = new UDP <DNSReply> { Payload = payload }; } } if (packet == null) { // This can never fail, so I'm not checking the output Generic.TryParse(buffer, index + (int)br.BaseStream.Position, count - 8, out Generic payload); packet = new UDP <Generic>() { Payload = payload }; } packet.SourcePort = sourcePort; packet.DestPort = destPort; packet.TotalLength = totalLength; packet.Checksum = checksum; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out EthernetII packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var dstMac = br.ReadBytes(6); var srcMac = br.ReadBytes(6); var etherType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet = null; switch (etherType) { case (ushort)EtherTypes.IPv4: { IPv4 payload; if (IPv4.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new EthernetII <IPv4> { Payload = payload }; } } break; case (ushort)EtherTypes.ARP: { ARP payload; if (ARP.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new EthernetII <ARP> { Payload = payload }; } } break; } if (packet == null) { Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload); // This can never fail, so I'm not checking the output packet = new EthernetII <Generic> { Payload = payload }; } packet.DstMac = dstMac; packet.EtherType = etherType; packet.SrcMac = srcMac; return(true); } } } catch (Exception) { packet = null; return(false); } }