Home > Writeups > DEADROP Forensics 6 - NIGHTJAR AFTERMATH

DEADROP Forensics 6 - NIGHTJAR AFTERMATH

A ZIP containing six post-incident artifacts, logs, a photo, a config, a README, a binary, and a pcap. Each hides one fragment of the flag using a different technique. The README encodes the final fragment via trailing-space whitespace steganography across 47 lines.

NIGHTJAR AFTERMATH

Overview

Six forensic artifacts. The flag is split into shards A–F (one per artifact), each hidden with a different technique. Recover all six shards and concatenate in order: A+B+C+D+E+F.

Shard A: DEADROP{six_     comm_log.pcap        (ICMP payload)
Shard B: artifacts_       workstation.dd       (raw disk slack space)
Shard C: one_             stego_brief.png      (blue channel LSB)
Shard D: truth_           sqlite_db.db         (VIEW definition)
Shard E: the_analyst_     timeline.evtx.b64    (JSON event field)
Shard F: perseveres}      README.txt           (whitespace steganography)

Shard A: comm_log.pcap

Open in Wireshark and filter for ICMP:

icmp

Most pings have generic payloads. One packet stands out with Sequence=99. Click it, inspect the ICMP data field: the payload is the shard in ASCII.

With tshark:

tshark -r comm_log.pcap -Y "icmp.seq == 99" -x
# or
tshark -r comm_log.pcap -Y "icmp" -T fields -e data.text 2>/dev/null | grep DEADROP

Python approach:

from scapy.all import rdpcap, ICMP, Raw

for pkt in rdpcap('comm_log.pcap'):
    if pkt.haslayer(ICMP) and pkt.haslayer(Raw):
        payload = pkt[Raw].load
        if b'DEADROP' in payload:
            print(payload)

Shard A: DEADROP{six_


Shard B: workstation.dd

The filesystem shows a system.log file, that's a decoy. The shard is written directly into raw disk space at offset 10240, outside the normal filesystem area.

# Option 1: strings
strings workstation.dd | grep SLACK
# Output: [SLACK:artifacts_:END]

# Option 2: raw hex search
xxd workstation.dd | grep -A1 "SLACK"

# Option 3: dd
dd if=workstation.dd bs=1 skip=10240 count=64 2>/dev/null | strings

The marker format is [SLACK:<shard>:END].

Shard B: artifacts_


Shard C: stego_brief.png

Standard LSB steganography in the blue channel (same technique as Forensics 2):

from PIL import Image

img  = Image.open('stego_brief.png')
pix  = img.load()
bits = []
for row in range(img.height):
    for col in range(img.width):
        bits.append(pix[col, row][2] & 1)  # blue LSB

chars = []
for i in range(0, len(bits), 8):
    byte = int(''.join(str(b) for b in bits[i:i+8]), 2)
    if byte == 0: break
    chars.append(chr(byte))
print(''.join(chars))

Shard C: one_


Shard D: sqlite_db.db

The obvious tables (ops_log, assets) don't contain the shard. Run a full schema dump:

sqlite3 sqlite_db.db .schema
# or
sqlite3 sqlite_db.db .dump

There's a VIEW definition:

CREATE VIEW hidden_assets AS
    SELECT * FROM ops_log WHERE notes='truth_'
    -- recovery_key:truth_

The shard is both in the WHERE clause and in the SQL comment. Visible in .schema, in .dump, and in the raw bytes of the file (strings sqlite_db.db | grep truth).

Shard D: truth_


Shard E: timeline.evtx.b64

The file is base64-encoded JSON masquerading as a Windows Event Log export. Strip the comment lines and decode:

grep -v '^#' timeline.evtx.b64 | base64 -d | python3 -m json.tool

Or in Python:

import base64, json

lines = [l for l in open('timeline.evtx.b64') if not l.startswith('#')]
events = json.loads(base64.b64decode(''.join(lines)))

for e in events:
    print(json.dumps(e, indent=2))

Look through all events carefully. EventID 4800 ("Workstation locked") has an unusual field: CorrelationActivityID. Standard Windows events don't have this field, it's the hiding spot.

{
  "EventID": 4800,
  "CorrelationActivityID": "the_analyst_",
  ...
}

Shard E: the_analyst_


Shard F: README.txt

The README itself is Shard F's carrier.

Extract the encoding:

Detect trailing spaces with cat -A (shows $ at line end, $ for trailing space):

cat -A README.txt
# lines ending in ' $' are bit 1, lines ending in '$' are bit 0

Shard F: perseveres}


Assembly

A: DEADROP{six_
B: artifacts_
C: one_
D: truth_
E: the_analyst_
F: perseveres}

Flag: DEADROP{six_artifacts_one_truth_the_analyst_perseveres}

Key Takeaway

Multi-artifact forensics requires breadth as much as depth. Each technique here (network carving, slack space, LSB steg, schema inspection, field enumeration, whitespace encoding) is individually straightforward, the challenge is knowing to apply each one and having the patience to look everywhere.

< Back to All Writeups