---
title: "Hidden in Plain Sight: PCAP Traffic Analysis"
description: "Recovering a flag from captured network traffic by identifying an unusual HTTP multipart upload and extracting the base64-encoded payload buried inside it."
date: 2025-11-08
authors: "Alpet Gexha"
tags: ["forensics", "pcap", "wireshark", "network", "base64", "http"]
ctf: "NullCTF 2025"
category: "Forensics"
difficulty: "Easy"
source: "/writeups/nullctf-2025-pcap"
---

# Hidden in Plain Sight: PCAP Traffic Analysis

We got a single file: `capture.pcap`. No other context. Classic forensics opener.

## First Look in Wireshark

Open the file, check the protocol breakdown under **Statistics → Protocol Hierarchy**:

- ~80% TCP
- ~18% HTTP
- ~2% DNS

No TLS, which means traffic is cleartext — good start. Filter for HTTP to cut the noise:

```
http
```

Around 340 packets, mostly GET requests for static assets. Nothing interesting until packet **187**: a `POST /upload` with a `Content-Type: multipart/form-data` body that is noticeably larger than the others — about 4.2 KB versus the typical few hundred bytes.

## Extracting The Upload

Right-click packet 187 → **Follow → HTTP Stream**. The raw stream shows:

```
POST /upload HTTP/1.1
Host: 10.0.0.42
Content-Type: multipart/form-data; boundary=----FormBoundary7MA4YWxk

------FormBoundary7MA4YWxk
Content-Disposition: form-data; name="file"; filename="notes.txt"
Content-Type: text/plain

dGhpcyBpcyBub3QgdGhlIGZsYWcgeW91IGFyZSBsb29raW5nIGZvcg==

------FormBoundary7MA4YWxk
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

{"checksum":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","payload":"TlVMTHtQY2FwX0hpZGRlbl9JblBsYTFuX1MxZ2h0fQ=="}
------FormBoundary7MA4YWxk--
```

> **Two base64 blobs, check both**
>
> The `file` field decodes to a decoy string. The interesting one is in the `metadata` JSON under the `payload` key — that is the one that matters.

## Decoding The Payload

```bash
echo "TlVMTHtQY2FwX0hpZGRlbl9JblBsYTFuX1MxZ2h0fQ==" | base64 -d
```

Output:

```
NULL{PcaP_Hidden_InPla1n_S1ght}
```

Done.

## Automating It With tshark

For anyone who wants to do this without clicking through Wireshark:

```bash
# Export all HTTP POST bodies
tshark -r capture.pcap \
  -Y "http.request.method == POST" \
  -T fields -e http.file_data \
  2>/dev/null | tr -d '\n'
```

Then pipe through a quick Python snippet to pull the `payload` field and decode:

```python
import json, base64, re

raw = open("http_bodies.txt").read()
match = re.search(r'"payload":"([A-Za-z0-9+/=]+)"', raw)
if match:
    print(base64.b64decode(match.group(1)).decode())
```

## What Made This Interesting

The challenge worked because most players would fixate on the `file` field and get the decoy string. The actual data was hidden one level deeper, in a JSON sub-field inside the same multipart body — something Wireshark does not highlight automatically.

The lesson: when a multipart upload looks bigger than it should, expand every part. Do not stop at the first base64 string you find.

**Flag:** `NULL{PcaP_Hidden_InPla1n_S1ght}`
