Modifying PCAPng File Structure using a Raw Hex Editor


By manually changing the Linktype using a hex editor in the Interface Description Block (IDB) of the PCAPng file will convince the packet analysis software that only 1 type of interfaces were available at the time of capture.

Published on April 14, 2021 by Tony E.

pcap hex zeek suricata brim

9 min READ

tl;dr
By manually changing the Linktype using a hex editor in the Interface Description Block (IDB) of the PCAPng file will convince the packet analysis software that only 1 type of interfaces were available at the time of capture.

WARNING: Throughout this post I reference “PCAP” and “PCAPng” interchangeably. I also perform operations on files who have the extension *.pcap while their file structure is actually *.pcapng . Everything in this post whether *.pcap or *.pcapng should be *.pcapng. Thank you.

In one of my recent blog posts I discussed how some packet analysis tools have trouble processing a PCAPng file containing more than 1 interface type. Specifically I had a PCAPng file containing:

  • LINKTYPE_ETHERNET (1)
  • LINKTYPE_LINUX_SLL (113)

See that post here.

At the bottom of that post I left with an indication that this could be done manually but I wasn’t quite sure how. This unanswered question has bothered me. I needed to know “Why?” and “How?”. This led to a path I never thought I’d cross: Manually editing raw hex to manipulate files.

My idea at the time was if we split the packets from the PCAPng file into 2 separate files each containing traffic from only 1 interface type, the packet analysis tools should have no problem processing them individually.

Using tshark I split the protocols into 2 files:

tshark -r <input_file.pcapng> -w eth.pcapng -Y "eth"
tshark -r <input_file.pcapng> -w sll.pcapng -Y "sll"

The above tshark commands will create 2 PCAPng files each containing only like-traffic using the display filter. With wireshark you can verify all the packets are alike within each file. Each tool tested (Zeek, Suricata, Brim & tcpdump) still gives the same error processing these new PCAPs as they did when processing the single PCAP containing both Layer-2 protocols. (see this blog post)

Hypothesis

I’m thinking there are still artifacts in the new PCAPng files referencing the additional interfaces from the original PCAPng file.

…but where?

A Clue

When you open the new PCAPng files (eth.pcapng & sll.pcapng), even though they each contain only 1 type of Layer-2 header, in the Capture File Properties you’ll see 2 types of interfaces listed under the “Link Type” column header.

Ah-ha! This data must still be contained in the file …but where?

Understanding the PCAPng File Structure

To understand what’s going on you’ll need to understand the PCAPng file structure.

To summarize our issue with this specific PCAPng file and condense the information I will NOT step through every header, block field and options, instead I’ll give a high level description. Everything you’ll need to know about the PCAPng file structure is in the documentation.

Below is an abstract image representing the compisition of our PCAPng file, reading from left–>right. The file is broken up into different sections called blocks. Below is a summary of the file blocks we’re interested in.

Block Types

  • Section Header Block (SHB): Every PCAPng file must have at least 1 of these blocks but can have more. This does NOT contain packet data. It more like meta data around the file itself like the OS and version of the system the PCAPng file was created.
  • Interface Description Block (IDB): This block contains the Linktype values. This is where an interface is identified as LINKTYPE_ETHERNET (1) or LINKTYPE_LINUX_SLL (113). The order of these blocks determines the interface ID value. The first Interface Description Block becomes interface ID: 0. All subsequent Interface Description Blocks not separated by SHB’s are incremented by 1.
  • Enhanced Packet Block (EPB): This block contains the actual packet data from Layer-2 to Layer-7 and also indicates which interface ID this packet was captured from.

Our PCAPng file closely resembles the “complex example” figure 6 from the documentation.

Our PCAPng file has 2 IDB blocks and inside each IDB is a different Link Type.

This is the source of our problem.

PCAPng Hex Dump

Looking at the PCAPng file using a hex editor, I’ve outlined the sections using the same colors as the image in the previous section. I’ve also highlighted some values using bright yellow and green. The values highlighted in yellow represent the Link type and the values highlighted in green are the associated Interface ID for each EPB.

NOTE: The above hex dump should be read Little-Endian. Not all captures will be Little-Endian, that is left up to your local operating system.

Block Type Highlighted Color HEX Decimal Meaning Notes Interface ID
IDP Yellow 0x71 113 LINKTYPE_LINUX_SLL Linux Cooked Capture 0
IDP Yellow 0x01 1 LINKTYPE_ETHERNET Ethernet Header 1
EPB Green 0x01 1 Use interface ID 1 none n/a
EPB Green 0x01 1 Use interface ID 1 none n/a
EPB Green 0x01 1 Use interface ID 1 none n/a

Using the below image, something worth noting is, some of the info is explicitly contianed in the data (‘included data’) and some of the info is derived meaning it’s not actually reflected in the bytes or bits but is derived based on it’s placement in the file structure. The first IDB block becomes ‘interface id: 0’, the second IDB becomes ‘interface id: 1’, etc …:

In our case, using the example eth.pcapng file:

  • All the packets reference interface ID: 1, which is the “LINKTYPE_ETHERNET” as their source interface.
  • None of the packets reference interface ID: 0, which is the “LINKTYPE_LINUX_SLL”.

We should be able to change the Link type in the first listed IDB from 0x71 –> 0x01 without casing an issue.

This will indicate to applications reading the PCAPng file that ‘this file was produced on a system that was capturing on 2 interfaces and both were LINKTYPE_ETHERNET’.

My Process

  1. Using tshark split out the Layer-2 protocols into separate PCAPng files: eth-before.pcap & sll-before.pcap
  2. Manually edit the Interface Description Blocks (IDB) using a hex editor, making both LINKTYPE fields the same, either 0x71 or 0x01, and naming the files eth-after.pcap & sll-after.pcap, respectively.
  3. Testing each pcap with: tcpdump, Suricata, Zeek & Brim

Definitions

Before
Each PCAP file contains only (1) Layer-2 protocol in the EPBs, but the SHB contains (2) IDBs with different LINKTYPEs.
After
Each PCAP file contains only (1) Layer-2 protocol in the EPBs and the SHB contains (2) IDBs which are the same LINKTYPE.

Results

After changing the values you can see from this screenshot, Wireshark now thinks both interfaces are the same.

Before

After

Compatibility Matrix

Tool Name Original Combined PCAP File eth-before.pcapng sll-before.pcapng eth-after.pcapng sll-after.pcapng
Wireshark Yes Yes Yes Yes Yes
tshark Yes Yes Yes Yes Yes
tcpdump No No No Yes:+1: Yes:+1:
zeek No No No Yes:+1: Yes:+1:
suricata No No No Yes:+1: Yes:+1:
Brim No No No Yes :+1: Yes:+1:

Example Processing the Before & After PCAPs

Zeek: eth-before.pcap & eth-after.pcap

Zeek: sll-before.pcap & sll-after.pcap

tcpdump: eth-before.pcap & eth-after.pcap

Wireshark Side-By-Side

This shows the meta-data around duration and file size the same, with the Hash values changing because of the 1 byte that was modified.

Packet View for Reference

If you wanted to correlate the Hex dump image from earlier in this post against how it’s shown in Wireshark, you would be looking at these 3 packets:

Questions

  1. Why didn’t you just delete the unused/unreferenced Interface Description Block (IDB)?
    Because of how the interfaces are ID’d, if all the packets we referencing ID #1 (the second IDB), I would have to re-write all the interface ID references in all the EPBs and point them to interface ID #0. I really just wanted to make as few changes as possible. Leaving an unused ‘ghost IDB’ didn’t seem to hurt anything as long as the LINKTYPE was the same.
  2. What hex editor did you use?
    I used the “hex editor” plugin for Notepad++. Since I don’t do this often, I don’t have a favorite tool.
  3. How was the original PCAP created containing multiple LINKTYPE’s?
    I’m not sure how the PCAP’s author originally created file but if you use linux and capture packets on a system that has multiple interfaces and use: tcpdump -i any this should generate a PCAP using Linux Cooked Capture (sll) and then again but this time specifying a single interface: tcpdump -i eth0 and merge those files together, you’ll get a mixed IDB in the final PCAP file. NOTE: You may have to convert one or both to PCAPng file format first before merging.
  1. https://pcapng.github.io/pcapng/draft-tuexen-opsawg-pcapng.html