Writeups SCTF

Provenance Writeup - SCTF Finals 2026

writeup for the provenance challenge in sctf finals 2026.

Contents

Category: Misc

Difficulty: Hard

Description

You are an art forger: trick the museum’s AI into cataloguing 10 paintings while keeping your changes imperceptible to the human conservator who spot-checks every submission.

You have 5 minutes, and the live model is hidden from you.

Try out the challenge!

Resources

Setup

docker compose up --build

Overview

Solution

Step 1: Identify the bouncer architecture

import torch
sd = torch.load("bouncer.pt", map_location="cpu")
print(sd.keys())                 # odict_keys(['conv1.weight', 'bn1.weight', 'bn1.bias', ... ])
print(sd["conv1.weight"].shape)  # [64, 3, 7, 7] -> standard ResNet-18

Step 2: Exploit the architectural transfer gap

Step 3: Run targeted MI-FGSM against the bouncer

def targeted_mifgsm(model, x_norm, eps=0.05, steps=40, momentum=1.0):
    step_size = eps / 50
    y_target  = torch.tensor([TARGET_IDX])  # ship = 8
    x_raw = x_norm * std + mean             # work in [0,1] to enforce eps box cleanly
    delta, g = torch.zeros_like(x_raw), torch.zeros_like(x_raw)

    for _ in range(steps):
        x_adv = ((x_raw + delta).clamp(0, 1) - mean) / std
        x_adv.requires_grad_(True)
        CrossEntropyLoss()(model(x_adv), y_target).backward()
        g = momentum * g + x_adv.grad / x_adv.grad.abs().mean()
        delta = (delta - step_size * g.sign()).clamp(-eps, eps)

    return ((x_raw + delta).clamp(0, 1) - mean) / std

Step 4: Pre-screen locally before submitting

adv_pil = tensor_to_pil(x_adv)
x_q     = pil_to_tensor(adv_pil).to(DEVICE)   # check quantized, not float
pred, _ = local_pred(model, x_q)
if pred == TARGET_IDX:
    return adv_pil, cur_eps
FailureAction
”Alterations are visible” (similarity)eps *= 0.80
”No longer sees an equestrian” (verifier)eps *= 0.85
”Flagged as equestrian” / “Wrong wing” (bouncer)should not occur after quantization-aware pre-screening; eps *= 1.1 as fallback

Flag

sctf{h0p3_y0u_3nj0y3d_f95m_02_p9d}

← Back to Blog