Kalos Cybersecurity LLC

Packet parsing and timestamp validation

FG09 · v23

1. Container workflow · 2. Linux validation · 3. Windows validation · 4. Create and verify your container

Alerts to Answers Analyst Field Guide · v1 review draft · Book v22

Purpose and context

An analyst receives a PCAPNG file. A packet reader displays a timestamp, but the analyst must show how the stored bytes produce that value. This lab uses the supplied captures to connect file structure, byte order, interface resolution and UTC conversion. A correct conversion does not establish that the capture clock was accurate.

Processing order and tools

Step Tool and output
Preserve and identify SHA-256 identifies the supplied capture and each derivative. Record origin, handling and scope.
Locate the packet block Read PCAPNG block lengths; identify the relevant section and interface. Do not guess fixed offsets.
Show the stored bytes Ubuntu xxd or od displays the timestamp bytes at the verified location.
Decode the value Python combines the high/low words using the section byte order and interface time units.
Cross-check TShark independently reports packet epoch times. Explain agreement and remaining clock uncertainty.

Files and prerequisites

Use the supplied PacketParsing.pcapng (20 packet records) and http-google101.pcapng (374). Preserve the originals; work on verified copies in a new folder. Python 3, a byte-dump utility and TShark are needed for the full exercise. No live capture, packet transmission or elevated privilege is required.

The current master is Packet_Parsing_Tool_Summary_v7.1.xlsx. Its companion MHT provides a reading copy of all six worksheets. The v7.1 author edits retain the technical corrections and verified offsets from the v7 review. Four tabs now have descriptive titles; an accidental text fragment was removed from G14.

What to submit

Submit the input hashes, tool versions, byte dumps, the located block boundaries, your integer calculation, TShark comparison, original screenshots and a short interpretation with limitations. Keep the complete command outputs. Label a converted capture as a derivative and retain its source.

Analyst takeaway: A timestamp interpretation should be traceable from the original file bytes to the displayed time.

1 Identify the capture and locate the timestamp

In Ubuntu, from the folder containing the verified working copies:

sha256sum PacketParsing.pcapng http-google101.pcapng
xxd -g1 -l 96 PacketParsing.pcapng

The expected PacketParsing.pcapng digest is:

9a487a177d6d5e080fe47bbf6f31d90df12b1597d68fab6f515aa7fab1595c39

The actual file begins with a 40-byte Section Header Block (SHB) and a 32-byte Interface Description Block (IDB). Its first Enhanced Packet Block (EPB) starts at byte 72 (0x48). The timestamp begins 12 bytes into that EPB, at byte 84 (0x54). These are measured locations in this file, not universal PCAPNG constants.

EPB location Field in this example
EPB +0 Block type; +4 is the total block length.
EPB +8 Interface ID. Use that interface's timestamp units/offset.
EPB +12 High 32-bit timestamp word.
EPB +16 Low 32-bit timestamp word.

Show exactly those eight bytes using either tool:

xxd -g1 -s 84 -l 8 PacketParsing.pcapng
od -An -v -tx1 -j84 -N8 PacketParsing.pcapng

The recorded byte sequence is:

6f bc 03 00 6f c0 0a ae

xxd -g1 groups single bytes; -s selects the starting byte and lowercase -l limits the byte count. od -An suppresses address labels; -tx1 selects hexadecimal one-byte values; -j skips bytes; -N limits the count. Neither command, by itself, interprets PCAPNG time.

Gotcha: Grouping eight bytes does not make the EPB timestamp an ordinary little-endian 64-bit integer. Decode the high and low words separately, then combine them.

2 Decode the two timestamp words

The reviewed section is little-endian. The relevant interface uses microseconds and an offset of zero. For this identified fixture, decode the eight bytes as two little-endian 32-bit words:

from datetime import datetime, timedelta, timezone
raw = bytes.fromhex('6f bc 03 00 6f c0 0a ae')
high = int.from_bytes(raw[:4], 'little')
low = int.from_bytes(raw[4:], 'little')
ticks = (high << 32) | low
seconds, micros = divmod(ticks, 1_000_000)
recorded = datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(
    seconds=seconds, microseconds=micros)
print(high, low, ticks)
print(recorded.isoformat(timespec='microseconds'))

Expected output for the supplied bytes:

244847 2919940207 1051612777463919
2003-04-29T10:39:37.463919+00:00

The left shift gives the high word its place in the counter. divmod preserves integer precision while separating seconds and microseconds. The UTC epoch plus that duration produces the recorded packet time.

File-based companion check

The supplied helper reads the actual capture, validates its known digest, walks block lengths, reads IDB timestamp options and checks every EPB. It deliberately rejects other captures rather than assuming their format properties.

python3 validate_supplied_pcaps.py PacketParsing.pcapng > packet-check.json

The report should show 20 packets, first EPB offset 72, and the decoded first time above. Its final packet is 2003-04-29T10:39:46.610023+00:00. Inspect the report instead of relying solely on successful process exit.

Gotcha: These fixtures use microseconds. Python datetime cannot retain arbitrary nanosecond precision. For a different file, determine section byte order, interface ID, if_tsresol and if_tsoffset before choosing the calculation or representation.

Analyst takeaway: Resolve the file and interface context before converting a counter into a time.

3 Cross-check with a packet reader

Using an installed TShark in the terminal:

tshark --version
tshark -n -r PacketParsing.pcapng -T fields \
  -e frame.number -e frame.time_epoch > tshark-times.tsv

-r reads the saved file. -n suppresses name resolution. -T fields and the -e selections print packet number and epoch time. Compare the first row with the integer result from the previous page.

1    1051612777.463919000

The extra displayed zeros do not establish nanosecond measurement accuracy. Compare numeric values without rounding away recorded precision. The prior review compared every EPB timestamp from both supplied files with TShark 4.6.0: all 394 matched.

Repeat with the second capture

http-google101.pcapng begins with a 132-byte SHB, a 136-byte IDB and a 62,572-byte Name Resolution Block. Its first EPB is at byte 62,840 (0xF578); the timestamp is at byte 62,852. Starting at byte 256 would not select its first packet.

xxd -g1 -s 62852 -l 8 http-google101.pcapng
python3 validate_supplied_pcaps.py http-google101.pcapng > http-check.json
tshark -n -r http-google101.pcapng -T fields \
  -e frame.number -e frame.time_epoch > http-tshark-times.tsv

The first timestamp bytes are ab cc 04 00 47 d9 76 d7. The first recorded time is 2012-10-22T20:38:53.206855Z; the last packet record is 2012-10-22T20:39:01.408940Z. The file contains 374 packet records.

Student task: Explain why the same eight-byte decoding method applies after locating the correct block, while the first capture's fixed offset does not. Show the high word, low word and integer counter in your own report.

Analyst takeaway: Tool agreement supports the decoding, not the accuracy or provenance of the capture clock.

4 ETL conversion: a separate derivative workflow

The supplied packetparsing_mytrace.etl contains Microsoft-Windows-NDIS-PacketCapture events. The earlier review found that an offline Pktmon conversion exited successfully but produced zero packets. That result did not prove the ETL was empty. Choose a converter for the recorded provider and retain the source.

The validated conversion used Microsoft's etl2pcapng v1.11.0:

.\etl2pcapng.exe .\packetparsing_mytrace.etl `
  .\packetparsing_mytrace.ndis.pcapng
Get-FileHash .\packetparsing_mytrace.etl -Algorithm SHA256
Get-FileHash .\packetparsing_mytrace.ndis.pcapng -Algorithm SHA256

The prior conversion wrote 781,383 frames across six Ethernet interfaces. Capinfos interface counts independently summed to 781,383. A TShark sample inspected the first ten records; that sample is not event-by-event equivalence validation of the whole derivative.

Derivative record

Record the ETL provider, source hash, converter version/hash, exact command, stdout/stderr, derivative hash, packet/interface counts and a documented sampling or full-validation strategy. Investigate warnings, dropped records and precision changes. Keep the original ETL and the failed zero-packet attempt.

This compact student kit contains only the two small PCAPNG fixtures. The large ETL source and converted derivative stay in the project evidence directory for an instructor-led extension. Do not rerun conversion over the retained derivative.

What the evidence can establish

A whole-file hash includes the capture's embedded timestamp bytes because they are part of the file content. It does not cover external filesystem times. Matching hashes also do not establish clock synchronization, complete traffic collection or authenticity before the baseline.

Analyst takeaway: Successful conversion means little until you validate the output against the source type and intended collection scope.

5 Student review and submission

  1. Identify the two capture hashes and the tool versions used.
  2. Show the first capture's SHB, IDB and EPB boundaries and derive the timestamp offset.
  3. Explain why the high/low words must be decoded separately.
  4. Compare the integer calculation with TShark and explain displayed precision versus clock accuracy.
  5. Repeat the block-location and time calculation for the second capture.
  6. Explain why zero packets from the wrong converter is not proof of an empty ETL.
  7. State what your checks establish and which questions remain unresolved.

Keep raw outputs and original screenshots. A screenshot should show the command, input filename, relevant bytes and complete result. Do not present this guide's expected values as proof of your own execution.

References and evidence

Guttman, B., White, D. R., & Walraven, T. (2022). Digital evidence preservation: Considerations for evidence handlers (NIST IR 8387). https://doi.org/10.6028/NIST.IR.8387

Tuexen, M., et al. (2026). PCAP now generic (pcapng) capture file format (Internet-Draft draft-ietf-opsawg-pcapng-05). https://www.ietf.org/archive/id/draft-ietf-opsawg-pcapng-05.html . This is a work-in-progress format reference, not a published RFC; the cited draft's stated expiry was September 18, 2026.

Wireshark Foundation. (n.d.). tshark(1). https://www.wireshark.org/docs/man-pages/tshark.html

Microsoft. (2023). etl2pcapng, release v1.11.0. https://github.com/microsoft/etl2pcapng/releases/tag/v1.11.0

Vim project. (n.d.). xxd(1). https://github.com/vim/vim/blob/master/runtime/doc/xxd.man

Python Software Foundation. (n.d.). datetime. https://docs.python.org/3/library/datetime.html

Local evidence: the v7 workbook review and QA/actual-validation.json, both original PCAPNG files, TShark epoch exports, ETL conversion log and capinfos output. This draft adds a hash-restricted teaching validator; it does not replace the retained review records or provide a general PCAPNG parser.

Preservation principle: Preserve what you can; document what you cannot preserve; verify every transition.

Student kit

Download the student scripts, worksheet and guide.

The companion retains its own source edition and documented test scope. Author approval does not replace a classroom run.

1. Container workflow · 2. Linux validation · 3. Windows validation · 4. Create and verify your container

Browser reference summary

Read all six worksheets in your browser or download the MHT browser archive. MHT handling depends on your browser; the HTML reading copy contains the same worksheet tables.

Companion lab

SL-04 — Packet parsing and timestamp validation: tasks, evidence submission and completion criteria.