cybersecurity · intermediate · ~15 min · safe pentest lab

Read the 24-byte pcap global header

Bounds-checked, alignment-safe binary parsing of a fixed-size header.

Challenge

Read and validate a pcap file's 24-byte global header — every forensic walk through a packet trace starts here.

Task

Implement int read_pcap_header(const uint8_t *buf, size_t n, pcap_hdr_t *out) where:

typedef struct {
    uint32_t magic;
    uint16_t version_major;
    uint16_t version_minor;
    int32_t  thiszone;
    uint32_t sigfigs;
    uint32_t snaplen;
    uint32_t linktype;
} pcap_hdr_t;

Parse all fields little-endian (assume a little-endian host).

Input

  • buf, n: a fixture byte buffer and its length, baked into the harness. A valid header is 24 bytes laid out as the struct, with magic first.
  • out: the struct to fill on success.

Output

Returns int: 0 if magic == 0xa1b2c3d4 and n >= 24 (filling out), -1 otherwise (including NULL inputs).

Example

24-byte buffer with magic d4 c3 b2 a1, version 2.4, snaplen 65535, linktype 1
read_pcap_header(buf, 24, &out)   ->   0, out.magic = 0xa1b2c3d4
n < 24, or wrong magic, or NULL    ->   -1

Edge cases

  • n < 24 returns -1.
  • thiszone is signed (int32_t) and may be negative.

Rules

  • Build each integer byte-by-byte with shifts; do not cast (uint32_t *)buf (alignment-unsafe).
  • Read no bytes past buf[n-1].

Why this matters

Every forensic walk through a packet trace starts here. Read 24 bytes, validate the magic, classify the link type.

Input format

A const byte buffer of at least 24 bytes representing a pcap file's global header.

Output format

0 on valid magic, -1 otherwise. Struct fields filled on success.

Constraints

No pointer casts. No reads past n. Magic must be 0xa1b2c3d4.

Starter code

#include <stdint.h>
#include <stddef.h>
typedef struct {
    uint32_t magic;
    uint16_t version_major;
    uint16_t version_minor;
    int32_t  thiszone;
    uint32_t sigfigs;
    uint32_t snaplen;
    uint32_t linktype;
} pcap_hdr_t;

int read_pcap_header(const uint8_t *buf, size_t n, pcap_hdr_t *out) {
    /* TODO */
    (void)buf; (void)n; (void)out;
    return -1;
}

Common mistakes

Casting (uint32_t *)buf (alignment-unsafe). Forgetting the n >= 24 bound. Treating thiszone as unsigned.

Edge cases to handle

n exactly 24 (just fits). thiszone negative. NULL pointers.

Complexity

O(1) — fixed 24-byte read.

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.