$ cat writeup.md…
$ cat writeup.md…
asisctf2026
Task: updated PKP-vault archive with public matrices, thousands of binary records, and a sealed flag blob; the first attachment was obsolete. Solution: redownload the new archive, exploit two transcript leaks to recover seven real secret keys, rebuild pack_key(), and decrypt the vault.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Please redownload the attachment!
English summary: the first local attachment was obsolete, and the real task was a different binary PKP-vault format stored in new_less_is_more.txz. The updated archive contains challenge.py and flag.enc; the goal is to recover the hidden real keys from leaked transcript records and use them to unseal the encrypted flag.
The decisive step was ignoring the old output.txt instance and re-downloading the attachment. The obsolete files under less_is_more/ describe a different challenge path; the solvable instance is the updated archive with:
MAGIC = b'ASIS117\x04'pub, records, sealedP=827, N=548, K=274, T=345, W=75, REAL=7, SLOTS=17The public helpers are all reproducible from the code:
chal(cmt, salt, msg)token(cmt, node)label(cmt, seed)take(seed, tag, n, k)Only REAL = 7 secret keys are genuine, but SLOTS = 17 public slots are published because 10 junk keys are mixed in.
The break comes from two bugs inside Box.one():
State carry-over bug
target = (37 * serial + 11) % T if sha256(b'v' + root) % 100 < 72: f[target] = self.state[target]
Instead of using int(b[target] != 0), one position often inherits the previous round state. A genuinely challenged round can therefore be treated as if it were revealable.
Decoy reveal bug
Fake path entries are chosen from indices with f[i] == 1, i.e. positions that correspond to real challenged rounds, and appended to path.
Together these bugs sometimes reveal both:
That is enough to turn one buggy record into a constraint on a real secret key. From a revealed challenged seed we recompute:
v = take(leaf_seed, b'n', N, K)
...
$ grep --similar