Writeups SCTF

Provenance Revenge Writeup - SCTF Finals 2026

writeup for the provenance revenge challenge in sctf finals 2026.

Contents

Category: Misc

Difficulty: Hard

Description

The museum retrained their bouncer, but someone on the inside left something in the new weights.

Get 20 forgeries catalogued with the new category using a single fixed perturbation pattern, and recover what was left inside.

Try out the challenge!

Resources

Setup

docker compose up --build

Overview

Why the Previous Approach Fails

Intended Solution

Step 1: Identify the Target Class via Spectral Signature Analysis

# 1. Hook avgpool, collect 512-dim activations for all training-set horse images
activations = []
model.avgpool.register_forward_hook(lambda m, i, o: activations.append(o.flatten(1)))
for img in train_horse_images:
    model(normalize(img))

A = torch.cat(activations)          # (N, 512)
A_c = A - A.mean(dim=0)             # centre
_, S, Vt = torch.linalg.svd(A_c, full_matrices=False)
v = Vt[0]                           # dominant direction = backdoor direction

# 2. Align with each class's FC weight vector
scores = (model.fc.weight @ v).abs()    # (10,)
suspected_target = scores.argmax()      # should be truck (9)

Step 2: Recover the Trigger via Neural Cleanse with L1 Regularisation

minδ  Ex[LCE ⁣(f ⁣(clamp(x+δ,0,1)),ytarget)]+λδ1\min_{\delta} \; \mathbb{E}_x \left[ \mathcal{L}_{\text{CE}}\!\left(f\!\left(\text{clamp}(x + \delta, 0, 1)\right),\, y_{\text{target}}\right) \right] + \lambda \|\delta\|_1
delta = torch.zeros(1, 3, 32, 32, requires_grad=True)
opt = torch.optim.Adam([delta], lr=0.01)

for step in range(4000):
    applied = (batch_raw + delta).clamp(0.0, 1.0)
    normed = (applied - mean) / std
    cls_loss = F.cross_entropy(model(normed), truck_targets)
    reg_loss = 0.05 * delta.abs().sum()
    (cls_loss + reg_loss).backward()
    opt.step()
    delta.data.clamp_(-0.5, 0.5)

Step 3: Validate Locally

Step 4: Encode and Submit

pixel_uint8 = round((0.5 + delta) * 255).clip(0, 255)

Flag

sctf{b4ckd00r_in_the_r3s7or4ti0n_s3rv1c3}

← Back to Blog