//exp-golomb
//exp-golomb Challenge Writeup
Category: Forensics
Author: vx
Flag: flag{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}

image.png
>Challenge Description
We received a zip file containing NAL units and a corrupted HEVC video file. The challenge name "exp-golomb" hints at Exponential-Golomb coding, which is used in H.264/H.265 (HEVC) video compression.
>Initial Analysis
First, let's extract and examine the contents:
unzip exp-golomb.zip
The archive contains:
video_raw.hevc- A raw HEVC video file (142KB)nal_units/directory with three subdirectories (A, B, C) containing.hedfiles
nal_units/
├── A/
│ ├── a.hed (54 bytes)
│ ├── b.hed (47 bytes) ← Different size!
│ ├── c.hed (54 bytes)
│ ├── d.hed (54 bytes)
│ └── e.hed (54 bytes)
├── B/
│ ├── a.hed (15KB) ← Much larger!
│ ├── b.hed (54 bytes)
│ └── c.hed (54 bytes)
└── C/
├── a.hed (54 bytes)
├── b.hed (54 bytes)
└── c.hed (28 bytes) ← Different size!
>Understanding the Problem
Let's try to play the video:
ffmpeg -i video_raw.hevc -f null -
Output shows multiple errors:
[hevc @ 0x...] Error parsing NAL unit #0.
Error while decoding stream #0:0: Invalid data found when processing input
The video is corrupted! The NAL (Network Abstraction Layer) units are damaged.
>Understanding HEVC Structure
HEVC videos require specific header NAL units at the beginning:
- VPS (Video Parameter Set) - NAL type 32
- SPS (Sequence Parameter Set) - NAL type 33
- PPS (Picture Parameter Set) - NAL type 34
These headers contain critical information for decoding the video frames.
>Analyzing NAL Units
Let's write a Python script to analyze the NAL unit types:
#!/usr/bin/env python3
import os
def read_nal_units(filename):
"""Read NAL units from a file"""
with open(filename, 'rb') as f:
data = f.read()
nal_units = []
i = 0
while i < len(data):
# Find start code (00 00 00 01)
if i + 4 <= len(data) and data[i:i+4] == b'\\x00\\x00\\x00\\x01':
start = i
i += 4
while i < len(data):
if i + 4 <= len(data) and data[i:i+4] == b'\\x00\\x00\\x00\\x01':
break
i += 1
nal_units.append(data[start:i])
else:
i += 1
return nal_units
def get_nal_type(nal_unit):
"""Get NAL unit type from HEVC NAL unit"""
if len(nal_unit) < 5:
return None
nal_header = nal_unit[4]
nal_type = (nal_header >> 1) & 0x3F
return nal_type
# Analyze video
video_nals = read_nal_units('video_raw.hevc')
print(f"Video has {len(video_nals)} NAL units")
print(f"First NAL type: {get_nal_type(video_nals[0])}") # Type 1 - corrupted!
# Analyze .hed files
for folder in ['A', 'B', 'C']:
for filename in sorted(os.listdir(f'nal_units/{folder}')):
if filename.endswith('.hed'):
filepath = f'nal_units/{folder}/{filename}'
nals = read_nal_units(filepath)
for nal in nals:
nal_type = get_nal_type(nal)
print(f"{folder}/{filename}: NAL type {nal_type}, size {len(nal)}")
Results:
Video: NAL types 0 and 1 (corrupted frame data, missing headers!)
Folder A: All NAL type 33 (SPS)
Folder B: All NAL type 34 (PPS)
Folder C: All NAL type 32 (VPS)
>The Solution
The video is missing its VPS, SPS, and PPS headers! We need to prepend the correct headers from the .hed files.
Looking at the file sizes, the unusual ones are likely the correct headers:
- C/c.hed (28 bytes) - smallest VPS
- A/b.hed (47 bytes) - different sized SPS
- B/a.hed (15KB) - much larger PPS (includes SEI data)
Let's fix the video:
#!/usr/bin/env python3
def read_file(filename):
with open(filename, 'rb') as f:
return f.read()
# Read the corrupted video
video_data = read_file('video_raw.hevc')
# Read the correct headers
vps = read_file('nal_units/C/c.hed') # VPS (type 32)
sps = read_file('nal_units/A/b.hed') # SPS (type 33)
pps = read_file('nal_units/B/a.hed') # PPS (type 34)
# Create fixed video: VPS + SPS + PPS + original video
fixed_video = vps + sps + pps + video_data
with open('fixed_video.hevc', 'wb') as f:
f.write(fixed_video)
print("Fixed video saved!")
>Verifying the Fix
ffmpeg -i fixed_video.hevc -f null -
Success! No more errors:
Stream #0:0: Video: hevc (Main), yuv420p(tv), 640x360 [SAR 1:1 DAR 16:9], 15 fps
>Extracting the Flag
Now let's extract frames from the video:
ffmpeg -i fixed_video.hevc frame_%03d.png
This extracts 45 frames. Looking through the frames, we can see text displaying the flag!
The visible text shows:
{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}
Adding the standard flag format: flag{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}
>Key Takeaways
- HEVC Structure: HEVC videos require VPS, SPS, and PPS headers before frame data
- NAL Units: Understanding NAL unit types is crucial for video forensics
- File Analysis: Unusual file sizes often indicate the correct/important files
- Exponential-Golomb: The challenge name referenced the coding scheme used in HEVC parameter sets
>Tools Used
ffmpeg- Video analysis and frame extractionhexdump- Binary file inspection- Python - Custom NAL unit parser
unzip- Archive extraction
Flag: flag{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}