The challenge
Files arrive inside and beside a collection of ZIP archives. Count what the archives claim, distinguish empty space from evidence, and find the census that does not add up.
One question per inner archive: "Determine zip.eocd_total_entries for evidence-drop-NNN.zip." An integer. The Single Solve asks about evidence-drop-001.zip, the Time Trial …-002, and Mastery …-003 and …-004 (one in each of two zips).
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "Seven-Zip, No Relation" (the title) | Not the 7-Zip program: it's Day 7, and it's about ZIP | — |
| "Inside and beside" | Zips within zips, and files next to them | Day 1's nested-zip handling, reused |
"Count what the archives claim" + the field zip. |
The End Of Central Directory record states how many entries the archive has. That's a claim, stored as a number, separate from the entries themselves | Answer the stated number; count the real entries only for comparison |
| "Empty space from evidence" | Padding, comments, or gaps inside an archive, versus real entries | The inventory reports the comment and the counts |
| "The census that does not add up" | An archive whose claim differs from what's really there | The inventory flags any mismatch |
How a ZIP counts its own contents
[PK 03 04 local header + data] … one per entry, front to back
[PK 01 02 central directory header] … one per entry: the index
[PK 05 06 End Of Central Directory] ← "total entries: N", where the index starts, comment length
Most tools read the archive backwards: they find the EOCD at the end, trust its count and offset, and then read the central directory. Nothing forces the three to agree, and that's how a zip can hide an entry (present, but not indexed) or claim one it doesn't have.
Finding the real EOCD: it ends with a variable-length comment, so it isn't at a fixed position. The solver scans back from the end for PK\x05\x06 whose comment length makes the record end exactly at the end of the file. A fake signature planted inside the comment doesn't fit that test.
What was in the files
| Mode | Archive | Bytes | EOCD claims | Local headers | Central headers | Census | Answer |
|---|---|---|---|---|---|---|---|
| Single Solve | evidence- |
410 | 2 | 2 | 2 | adds up | 2 |
| Time Trial | evidence- |
604 | 3 | 3 | 3 | adds up | 3 |
| Mastery set 1 | evidence- |
798 | 4 | 4 | 4 | adds up | 4 |
| Mastery set 2 | evidence- |
992 | 5 | 5 | 5 | adds up | 5 |
Each archive N held N+1 rooms (room-01/item-N.txt … room-(N+1)/item-N.txt), with no comment and no padding. No census failed to add up in our four. As with the other Metadata challenges, the prompt describes the whole pool, and the solver is ready for the odd one out.
Single Solve: CORRECT in 18 seconds
Started at 15:50:40 UTC. The outer zip's SHA-256 matched. Reading evidence-drop-001.zip's EOCD gave total 2, matching 2 local and 2 central headers. 2 was CORRECT at 15:50:58, flag 4d8aefd4…7585.
The solver, and a snag in the shared code
Our solver builds on Portable Deception's (Day 6) and adds the field …-zip-eocd-total-entries, returning the EOCD's stated total, including ZIP64's 8-byte total when the normal field is 0xFFFF.
The first test run failed: "can't tell which file it's about … files []". Day 1's shared solve() drops every zip from the list of possible targets, because for six days every question was about files inside a zip. This was the first question about a zip itself. The fix lives in Day 7 only: its own solve() uses Day 1's scoping unchanged, and keeps zip members as candidates for this one field. Every earlier day still behaves exactly as before, and the previous day's tests were re-run to confirm it.
6 tests, all passing before any timed run: - the real file; - counts of 0, 1, 3, and 7; - an EOCD claiming 5 over 2 real entries, answered 5, because the claim is what's asked; - a fake EOCD planted in the comment, ignored; - the Mastery shape (inner zips within two outer zips, one with a false claim); - an archive with no EOCD, which stops.
Time Trial: 2.75 s of a 7-second clock
started_at 2026-10-07T15:52:14.096Z deadline 2026-10-07T15:52:21.096Z
artifact metadata-day-07-evidence.zip 352 bytes sha256 8bfad1bf061e0099… (checked)
d07-zip-002-zip-eocd-total-entries: 3
start 1662 ms
artifact 326 ms
solve 1 ms
submit 757 ms
TOTAL 2746 ms
result CORRECT flag b7373c4d…feb
Mastery: 1.82 s of a 7-second clock, first attempt
started_at 2026-10-07T15:52:19.553Z deadline 2026-10-07T15:52:26.553Z
artifact metadata-forensics-day-07-seven-zip-no-relation-mastery.zip 1038 bytes sha256 fea81c477d8d746b… (checked)
set1.d07-zip-003-zip-eocd-total-entries: 4
set2.d07-zip-004-zip-eocd-total-entries: 5
start 393 ms
artifact 588 ms
solve 1 ms
submit 835 ms
TOTAL 1818 ms
result CORRECT flag 3c2e4e8a…410c
Time to solve
All three modes were solved in 1 min 41 s, from the Single Solve start at 15:50:40 UTC to the Mastery CORRECT at 15:52:21 UTC, with about a minute in between spent building the solver, working around Day 1's zip filter, and running the tests. Each mode went through on the first submit: the Single Solve in 18 s, the Time Trial in 2.75 s of 7 s, and the Mastery in 1.82 s of 7 s.
The first week of Metadata, in one table
| Day | Challenge | What was read | Answer form |
|---|---|---|---|
| 1 | You Must Be This Hash to Ride | Names, sizes, hashes from zip headers | text / hashes |
| 2 | Looks Can Be Deceiving | First 16 bytes (magic) | 32 hex chars |
| 3 | BOM Voyage | A UTF-8 byte order mark | true / false |
| 4 | Picture This | JPEG SOF frame header | WxH |
| 5 | Chunk Norris | PNG IHDR chunk | WxH |
| 6 | Portable Deception | PDF header version | x. or none |
| 7 | Seven-Zip, No Relation | ZIP EOCD total entries | integer |
Every day's solver builds on the previous day's, so Day 7's carries the whole week. All seven were solved in all three modes.
Takeaways
- An archive's count is a claim. The EOCD says how many entries there are; the local headers are what's really there. Asked for the claim, answer the claim, and check the reality separately.
- Find structures by fit, not by first match. The real EOCD is the one whose comment length ends exactly at the end of the file.
- Shared code carries old assumptions. "Questions are about files inside zips" held for six days and silently excluded zips. A test caught it before any submit, and the fix stayed local so nothing earlier could break.