Skip to content

SECURE_CONNECTION//PRESS[CTRL+J]FOR ROOT ACCESS

BACK TO INTEL
ForensicsEasy

Exp Golomb

CTF writeup for Exp Golomb from Backdoor

//exp-golomb

//exp-golomb Challenge Writeup

Category: Forensics

Author: vx

Flag: flag{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}

image.png

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:

bash

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 .hed files
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:

bash

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:

  1. VPS (Video Parameter Set) - NAL type 32
  2. SPS (Sequence Parameter Set) - NAL type 33
  3. 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:

python

#!/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:

python

#!/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

bash

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:

bash

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

  1. HEVC Structure: HEVC videos require VPS, SPS, and PPS headers before frame data
  2. NAL Units: Understanding NAL unit types is crucial for video forensics
  3. File Analysis: Unusual file sizes often indicate the correct/important files
  4. Exponential-Golomb: The challenge name referenced the coding scheme used in HEVC parameter sets

>Tools Used

  • ffmpeg - Video analysis and frame extraction
  • hexdump - Binary file inspection
  • Python - Custom NAL unit parser
  • unzip - Archive extraction

Flag: flag{h265_3nc0d1ng_1s_r34lly_g00d_f0r_4K_v1d}