diff --git a/patterns/pcapng.hexpat b/patterns/pcapng.hexpat index 5506bd91..5bfd4bdd 100644 --- a/patterns/pcapng.hexpat +++ b/patterns/pcapng.hexpat @@ -1,39 +1,27 @@ #pragma description PcapNG #pragma MIME application/vnd.tcpdump.pcapng #pragma author 5h4rrK +#pragma author Antonio Vázquez Blanco + +#define MAX_VALUE_U64 0xffffffffffffffff import std.mem; import std.core; -import std.math; import std.io; -#define MAX_VALUE_U64 0xffffffffffffffff - -fn format_version(auto version){ - return std::format( - "{}.{}", version.major, version.minor - ); -}; - - -fn is_valid_len(auto val){ - if (val == MAX_VALUE_U64){ - return std::format("[Not Specified]"); - } - else{ - return val; - } -}; - enum PcapOrder : u32{ Little = 0x1a2b3c4d, Big = 0x4d3c2b1a, }; -struct Version { - u16 major; - u16 minor; -}; +// Perform a read to get the endianness of the file and set +// the default endianness acordingly. +u32 order = std::mem::read_unsigned(0x8, 0x4); +if (order == PcapOrder::Little) { + std::core::set_endian(std::mem::Endian::Little); +} else { + std::core::set_endian(std::mem::Endian::Big); +} enum BlockType : u32{ // Mandatory Blocks @@ -79,6 +67,119 @@ enum BlockType : u32{ }; +enum SHBType : u16 { + EndOfOpt = 0x0, + Hardware = 0x2, + OS = 0x3, + Application = 0x4, + EndOfOpt = 0x0 +}; + +enum IDHType : u16 { + EndOfOpt = 0, + Name = 2, // UTF-8 device name (e.g., "eth0") + Description = 3, // UTF-8 device description + IPv4Addr = 4, // IPv4 address + netmask (8 bytes) + IPv6Addr = 5, // IPv6 address + prefix len (17 bytes) + MACAddr = 6, // MAC address (6 bytes) + EUIAddr = 7, // EUI-64 address (8 bytes) + Speed = 8, // Interface speed (bps, 8 bytes) + TimestampRes = 9, // Timestamp resolution (1 byte) + TimeZone = 10, // Time zone (4 bytes) + Filter = 11, // Capture filter string + OS = 12, // OS name (UTF-8 string) + FCSLength = 13, // Frame Check Sequence length (1 byte) + TimestampOffset = 14, // Timestamp offset (8 bytes) + Hardware = 15, // Variable length + TxSpeed = 16, // 8bytes + RxSpeed = 17 // 8bytes +}; + +enum NameResolutionType: u16 { + EndOfRecord = 0x00, + IPv4 = 0x01, + IPv6 = 0x02 +}; + +enum InterfaceStatsType : u16 { + EndOfOpt = 0, + Comment = 1, // isb_comment + StartTime = 2, // isb_starttime + EndTime = 3, // isb_endtime + IfRecv = 4, // isb_ifrecv + IfDrop = 5, // isb_ifdrop + FilterAccept = 6, // isb_filteraccept + OSdrop = 7, // isb_osdrop + UserDeliver = 8, // isb_usrdeliv +}; + +enum EnhancedPacketType : u16 { + EndOfOpt = 0x0, + Flags = 0x2, + Hash = 0x3, + DropCount = 0x4, + PacketId = 0x5, + Queue = 0x6, + Verdict = 0x7, +}; + +enum PacketBlockType : u16 { + Flags = 0x2, + Hash = 0x3, + EndOfOpt = 0x0, +}; + +struct Option { + if (this.parent.block_type == BlockType::SectionHeader) { + SHBType option_type; + } else if(this.parent.block_type == BlockType::InterfaceDesc) { + IDHType option_type; + } else if (this.parent.block_type == BlockType::NameResolution) { + NameResolutionType record_type[[name("record")]]; + } else if (this.parent.block_type == BlockType::InterfaceStats){ + InterfaceStatsType option_type; + } else if (this.parent.block_type == BlockType::EnhancedPacket) { + EnhancedPacketType option_type; + } else if (this.parent.block_type == BlockType::Packet){ + PacketBlockType option_type; + } + u16 option_len; + + if (option_len > 0){ + char data[option_len]; + } else{ + return; + } + u8 pad_size = (4 - ( $ % 4 )) % 4; + $ = $ + pad_size; +}; + +struct Version { + u16 major; + u16 minor; +}; + +fn format_version(auto version){ + return std::format( + "{}.{}", version.major, version.minor + ); +}; + +fn is_valid_len(auto val){ + if (val == MAX_VALUE_U64){ + return std::format("[Not Specified]"); + } + else{ + return val; + } +}; + +struct SectionHeaderBlockBody { + PcapOrder sectionbyteorder; + Version version [[name("Version"), format("format_version")]]; + u64 section_len [[name("SectionLen"), format("is_valid_len")]]; +}; + enum LinkType : u16 { LINKTYPE_NULL = 0, LINKTYPE_ETHERNET = 1, @@ -196,335 +297,104 @@ enum LinkType : u16 { LINKTYPE_ETW = 290 }; -enum SHBType : u16{ - EndOfOpt = 0x0, - Hardware = 0x2, - OS = 0x3, - Application = 0x4, - EndOfOpt = 0x0 -}; - -enum IDHType : u16 { - EndOfOpt = 0, - Name = 2, // UTF-8 device name (e.g., "eth0") - Description = 3, // UTF-8 device description - IPv4Addr = 4, // IPv4 address + netmask (8 bytes) - IPv6Addr = 5, // IPv6 address + prefix len (17 bytes) - MACAddr = 6, // MAC address (6 bytes) - EUIAddr = 7, // EUI-64 address (8 bytes) - Speed = 8, // Interface speed (bps, 8 bytes) - TimestampRes = 9, // Timestamp resolution (1 byte) - TimeZone = 10, // Time zone (4 bytes) - Filter = 11, // Capture filter string - OS = 12, // OS name (UTF-8 string) - FCSLength = 13, // Frame Check Sequence length (1 byte) - TimestampOffset = 14, // Timestamp offset (8 bytes) - Hardware = 15, // Variable length - TxSpeed = 16, // 8bytes - RxSpeed = 17 // 8bytes -}; - -enum NameResolutionType: u16 { - EndOfRecord = 0x00, - IPv4 = 0x01, - IPv6 = 0x02 -}; - -enum InterfaceStatsType : u16 { - EndOfOpt = 0, - Comment = 1, // isb_comment - StartTime = 2, // isb_starttime - EndTime = 3, // isb_endtime - IfRecv = 4, // isb_ifrecv - IfDrop = 5, // isb_ifdrop - FilterAccept = 6, // isb_filteraccept - OSdrop = 7, // isb_osdrop - UserDeliver = 8, // isb_usrdeliv -}; - -enum EnhancedPacketType : u16 { - EndOfOpt = 0x0, - Flags = 0x2, - Hash = 0x3, - DropCount = 0x4, - PacketId = 0x5, - Queue = 0x6, - Verdict = 0x7, -}; - -enum PacketBlockType : u16 { - Flags = 0x2, - Hash = 0x3, - EndOfOpt = 0x0, -}; - - -struct Option { - - if (this.parent.block_type == BlockType::SectionHeader) { - SHBType option_type; - } else if(this.parent.block_type == BlockType::InterfaceDesc) { - IDHType option_type; - } else if (this.parent.block_type == BlockType::NameResolution) { - NameResolutionType record_type[[name("record")]]; - } else if (this.parent.block_type == BlockType::InterfaceStats){ - InterfaceStatsType option_type; - } else if (this.parent.block_type == BlockType::EnhancedPacket) { - EnhancedPacketType option_type; - } else if (this.parent.block_type == BlockType::Packet){ - PacketBlockType option_type; - } - u16 option_len; - - if (option_len > 0){ - char data[option_len]; - } else{ - return; - } - // u8 pad_size = (4 - ( $ % 4 )); - u8 pad_size = (4 - ( $ % 4 )) % 4; - // if(this.parent.block_type == BlockType::InterfaceStats) { - // std::print("Current Pos {:#x} {:#x}",$, pad_size); - // } - - $ = $ + pad_size; -}; - - -struct SectionHeaderBlock { - BlockType block_type; - u32 length; - PcapOrder sectionbyteorder; - Version version [[name("Version"), format("format_version")]]; - u64 section_len [[name("SectionLen"), format("is_valid_len")]]; - u64 prev_pos = $; - Option options [ while( $ < (prev_pos + length - 28))]; - u32 block_length [[name("BlockLen")]]; - -}; - - -struct NameResolutionBlock { - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - u64 prev_pos = $; - Option records [ while($ < (prev_pos + block_len1 - 12)) ]; - u32 block_len2[[name("BlockLen2")]]; -}; - -struct SystemJournalExportBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - char data[block_len1]; - $ = $ + (4 - ($ % 4 ) ); // Padding - u32 block_len2[[name("BlockLen2")]]; -}; - -struct CustomBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - u32 pen[[name("PrivateEnterpriseNumber")]]; - char data[block_len1]; - u64 prev_pos = $; - $ = $ + (4 - ($ % 4 ) ); // Padding - Option options [while($ < (prev_pos + block_len1 - 16))] [[name("Options")]]; - u32 block_len2[[name("BlockLen2")]]; -}; - -struct InterfaceBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; +struct InterfaceDescBlockBody { LinkType link_type [[name("LinkType")]]; u16 reserved [[name("Reserved")]]; u32 snap_len [[name("SnapLen")]]; - u64 prev_pos = $; - Option options [ while( $ < (prev_pos + block_len1 - 20))]; - u32 block_len2[[name("BlockLen2")]]; }; -struct EnhancedPacketBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; +struct EnhancedPacketBlockBody { u32 interface_id[[name("InterfaceID")]]; u64 timestamp[[name("Timestamp")]]; u32 captured_len[[name("CapturedLen")]]; u32 pkt_len[[name("PacketLen")]]; char data[captured_len][[name("Data")]]; - // 32 (BlockType + BlockLen1 + InterfaceID + Timestamp + CapturedLen + PacketLen + BlockLen2) - $ = $ + (block_len1 - captured_len - 32); - u64 prev_pos = $; - // Current Pos - Prev Pos - 4 (BlockLen2) - // std::print("Option Size :: {:#x}", ($ - prev_pos)); - if (($ - prev_pos ) > 0) { - Option options [ while( $ < ( prev_pos + ($ - prev_pos ) ) ) ]; - } - u32 block_len2[[name("BlockLen2")]]; +}; +struct NameResolutionBlockBody { + // This block is empty, only contains options. }; -struct SimplePacketBlock { - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; +struct InterfaceStatsBlock { + u32 interface_id[[name("InterfaceID")]]; + u64 timestamp[[name("Timestamp")]]; +}; + +struct SimplePacketBlockBody { u32 pkt_len[[name("PacketLen")]]; char data[[name("Data")]]; - u8 pad_size = (4 - ( $ % 4 )) % 4; - $ = $ + pad_size; - u32 block_len2[[name("BlockLen2")]]; }; // Obsolete! -struct PacketBlock { - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - u16 interface_id[[name("InterfaceID")]]; - u16 drop_count[[name("DropCount")]]; +struct PacketBlockBody { + std::print("Obsolete Packet Block Body at offset {:#x}\n", $); + u16 interface_id[[name("InterfaceID")]]; + u16 drop_count[[name("DropCount")]]; u64 timestamp[[name("Timestamp")]]; u32 captured_len[[name("CapturedLen")]]; u32 pkt_len[[name("PacketLen")]]; - if (block_len1 > 32){ + if (parent.block_body_len > 20){ char data[captured_len]; } - u32 block_len2[[name("BlockLen2")]]; }; -enum CompressionType: u8 { - Uncompressed = 0x0, - LempelZiv = 0x1, - Gzip = 0x2 +struct CustomBlockBody { + u32 pen[[name("PrivateEnterpriseNumber")]]; + char data[parent.block_body_len-4]; }; enum EncryptionType : u32 { - TLS = 0x544c534b, /* TLS Key Log */ - SSH = 0x5353484b, /* SSH Key Log */ - WIREGUARD = 0x57474b4c, /* WireGuard Key Log */ - ZIGBEE_NWK_KEY = 0x5a4e574b, /* Zigbee NWK Key */ - ZIGBEE_APS_KEY = 0x5a415053 /* Zigbee APS Key */ -}; - -enum FixedLengthType : u8 { - // Experimental -}; - -// Experimental -struct CompressionBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - CompressionType comp_type [[name("Compresssion")]]; - char data[block_len1]; - u32 block_len2[[name("BlockLen2")]]; + TLS = 0x544c534b, // TLS Key Log + SSH = 0x5353484b, // SSH Key Log + WIREGUARD = 0x57474b4c, // WireGuard Key Log + ZIGBEE_NWK_KEY = 0x5a4e574b, // Zigbee NWK Key + ZIGBEE_APS_KEY = 0x5a415053 // Zigbee APS Key }; -struct EncryptionBlock{ - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; +struct EncryptionBlockBody { EncryptionType comp_type [[name("Encryption")]]; - u32 secrets_len[[name("SecretsLength")]]; + u32 secrets_len[[name("SecretsLength")]]; char data[secrets_len]; - padding[-$ & 3]; - // https://ietf-opsawg-wg.github.io/draft-ietf-opsawg-pcap/draft-ietf-opsawg-pcapng.html#section-4.7-6.6.1 - // No DSB-specific options are currently defined - // Option options; - u32 block_len2[[name("BlockLen2")]]; -}; - -// Experimental -struct FixedLengthBlock { - BlockType block_type[[name("BlockType")]]; - u32 block_len1[[name("BlockLen1")]]; - FixedLengthType comp_type [[name("FixedLength")]]; - char data[block_len1]; - u32 block_len2[[name("BlockLen2")]]; }; -struct InterfaceStatsBlock { +struct Block { BlockType block_type[[name("BlockType")]]; u32 block_len1[[name("BlockLen1")]]; - u32 interface_id[[name("InterfaceID")]]; - u64 timestamp[[name("Timestamp")]]; - if(block_len1 > 24) { - u64 prev_pos = $; - Option options [ while( $ < (prev_pos + block_len1 - 24))]; - } - u32 block_len2[[name("BlockLen2")]]; -}; - -struct PCAPng{ - if (std::mem::eof()){ - break; - } - if (order == PcapOrder::Little){ - le u32 block_type = std::mem::read_unsigned($, 0x4, std::mem::Endian::Little); - } else { - be u32 block_type = std::mem::read_unsigned($, 0x4, std::mem::Endian::Big); - } - // std::print("{} , {:#x}, {:#x}", "Parsing", $, block_type); - // std::print("Parsing : Offset({:#x}), Order({:#x}), BlockType({:#x})", $, order, block_type); + // Block body + u32 block_body_len = block_len1-12; + u64 block_body_end = $ + block_body_len; if (block_type == BlockType::SectionHeader) { - if (order == PcapOrder::Little) { - le SectionHeaderBlock SHB; - } else { - be SectionHeaderBlock SHB; - } + SectionHeaderBlockBody SHB; } else if (block_type == BlockType::InterfaceDesc) { - if (order == PcapOrder::Little) { - le InterfaceBlock IDH; - } else { - be InterfaceBlock IDH; - } + InterfaceDescBlockBody IDH; } else if (block_type == BlockType::EnhancedPacket) { - if (order == PcapOrder::Little) { - le EnhancedPacketBlock EBP; - } else { - be EnhancedPacketBlock EBP; - } + EnhancedPacketBlockBody EBP; } else if (block_type == BlockType::NameResolution) { - if (order == PcapOrder::Little) { - le NameResolutionBlock NRB; - } else { - be NameResolutionBlock NRB; - } + NameResolutionBlockBody NRB; } else if (block_type == BlockType::InterfaceStats) { - if (order == PcapOrder::Little) { - le InterfaceStatsBlock ISB; - } else { - be InterfaceStatsBlock ISB; - } + InterfaceStatsBlock ISB; } else if (block_type == BlockType::SimplePacket) { - if (order == PcapOrder::Little) { - le SimplePacketBlock SPB; - } else { - be SimplePacketBlock SPB; - } + SimplePacketBlockBody SPB; } else if (block_type == BlockType::Packet) { - if (order == PcapOrder::Little) { - le PacketBlock PB; - } else { - be PacketBlock PB; - } + PacketBlockBody PB; } else if (block_type == BlockType::Custom) { - if (order == PcapOrder::Little) { - le CustomBlock CB; - } else { - be CustomBlock CB; - } + CustomBlockBody CB; } else if (block_type == BlockType::CustomNoCopy) { - if (order == PcapOrder::Little) { - le CustomBlock CBN; - } else { - be CustomBlock CBN; - } + CustomBlockBody CBN; } else if (block_type == BlockType::Decryption) { - if (order == PcapOrder::Little) { - le EncryptionBlock DSB; - } else { - be EncryptionBlock DSB; - } + EncryptionBlockBody DSB; } else { - std::print("Unknown BlockType at offset {:#x}\n", $); - break; + char block[block_body_len][[name("Block Body Data")]]; + std::print("Unknown Block type at offset {:#x}\n", $); } -} [[inline]]; - + // Block body must be aligned to 32 bit (4 byte) + std::mem::AlignTo<4>; + // Block options + Option options [ while( $ < block_body_end)]; + u32 block_len2[[name("BlockLen2")]]; + if (block_len1 != block_len2) { + std::print("Inconsistent Block size at offset {:#x}\n", $); + } +}; -u32 order = std::mem::read_unsigned(0x8, 0x4); -PCAPng PcapNG [while(!std::mem::eof())] @0x00; +Block PcapNG [while(!std::mem::eof())] @0x00; \ No newline at end of file