Сокровище (Treasure)
Сокровище (Treasure)
Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-04-05 | Status: Solved Techniques: book_cipher_decryption, chapter_word_indexing, first_letter_extraction, unicode_smart_quote_handling
Summary
Task: Book cipher themed around the Beale Ciphers mystery, with encoded coordinates referencing War and Peace (Maude translation, Gutenberg #2600). Solution: Identify chapter+word-position format in Book One, extract first letters of each referenced word, handling Unicode smart quotes for correct word counting.
Сокровище (Treasure) — Hackerlab
Description
"В наследство я получил только жалкую коробку с двумя листами бумаги. Через несколько месяцев после этого мне пришло несколько романов от Эйлмер и Луизы Мод. До сих пор не понимаю зачем мне это, но возможно за этим скрывается огромное богатство."
English summary: You inherited a box with two sheets of paper. Months later, you received novels from "Aylmer and Louise Maude." The task is to decode the treasure coordinates using these clues.
Files:
task.zipcontaining:Advice— a Russian text with advice about dedicating time to the task (thematic red herring styled after the Beale papers advisory letter)Treasure— encoded coordinates (8 lines of comma-separated numbers)
Treasure file contents
1, 71, 12, 21
1, 11, 15, 18
5, 10, 55 , 1, 47
2, 64, 11
4, 36, 65
8, 70, 8
10, 26, 28
1, 6, 11
Analysis
1. Identifying the cipher type — Beale Cipher theme
The task description is a direct reference to the famous Beale Ciphers — a 19th century mystery about an encrypted treasure location supposedly buried in Virginia by Thomas J. Beale. Key parallels:
- "Box with two sheets of paper" → mirrors the Beale papers (three ciphertexts in a box)
- "Treasure" / "enormous wealth" → the Beale treasure story
- The
Advicefile is styled exactly like the advisory letter that accompanied the Beale papers — it warns about not wasting too much time on the puzzle. This is a red herring and NOT the cipher key.
2. Identifying the key text — War and Peace (Maude translation)
The critical clue is: "Эйлмер и Луизы Мод" = Aylmer Maude and Louise Maude — the famous husband-and-wife team who translated Leo Tolstoy's works into English. Their most important translation is "War and Peace", available on Project Gutenberg as eBook #2600.
This is the key text for the book cipher.
3. Understanding the encoding format
Each line in the Treasure file follows the pattern:
chapter_number, word_position_1, word_position_2, ...
- First number on each line = chapter number within Book One of War and Peace (Maude translation)
- Remaining numbers = word positions within that chapter (1-indexed)
- Take the first letter of each word at the specified position
4. Critical implementation detail — Unicode smart quotes
The Gutenberg text uses Unicode "smart quotes" (U+2019 RIGHT SINGLE QUOTATION MARK) for apostrophes in contractions like "don't". The word extraction regex MUST include this character as part of words, otherwise contractions get split into two words (e.g., "don" + "t"), shifting all subsequent word numbering and producing incorrect results.
Solution
Decoding table
| Line | Chapter | Word positions | Words found | Letters |
|---|---|---|---|---|
| 1 | Ch.I | 71, 12, 21 | call, of, don't | c, o, d |
| 2 | Ch.I | 11, 15, 18 | estates, But, you | e, B, y |
| 3 | Ch.V | 10, 55, 1, 47 | the, head, And, nations | t, h, A, n |
| 4 | Ch.II | 64, 11 | known, society | k, s |
| 5 | Ch.IV | 36, 65 | bored, room | b, r |
| 6 | Ch.VIII | 70, 8 | of, begin | o, b |
| 7 | Ch.X | 26, 28 | evening, Anna | e, A |
| 8 | Ch.I | 6, 11 | Lucca, estates | L, e |
| |
Raw decoded text: codeByREDACTED
- First 6 characters confirm the flag format:
CODEBY - Remaining 14 characters (lowercased):
REDACTED= "thanks bro Beale" — a nod to Thomas J. Beale
Solution script
python read-only • copy allowed#!/usr/bin/env python3 """Book Cipher decoder for Hackerlab 'Сокровище' (Treasure) Key text: War and Peace by Tolstoy, Maude translation (Gutenberg #2600) Format: chapter_in_book_one, word_pos1, word_pos2, ... → first letters """ import re with open('war_and_peace.txt', 'r') as f: # Gutenberg #2600 text = f.read() # Skip Gutenberg header body_start = text.find('*** START OF THE PROJECT GUTENBERG EBOOK') body_start = text.find('\n', body_start) + 1 body = text[body_start:] def extract_words(txt): """Extract words handling smart quotes (U+2019) and em-dashes""" txt = txt.replace('\u2014', ' ') # em-dash → space txt = txt.replace('\u2013', ' ') # en-dash → space txt = txt.replace('\u201c', ' ') # left double quote → space txt = txt.replace('\u201d', ' ') # right double quote → space # Include U+2018/U+2019 (smart single quotes) for contractions like don't words = re.findall(r"[a-zA-Z\u00C0-\u00FF\u2018\u2019]+", txt) words = [w.strip('\u2018\u2019') for w in words] return [w for w in words if w] def roman_to_int(s): vals = {'I':1,'V':5,'X':10,'L':50,'C':100} result = 0 for i, c in enumerate(s): if i+1 < len(s) and vals.get(c,0) < vals.get(s[i+1],0): result -= vals.get(c,0) else: result += vals.get(c,0) return result # Find Book One boundaries book_one_start = body.find('\n\nBOOK ONE:') book_two_start = body.find('\n\nBOOK TWO:') book_one = body[book_one_start:book_two_start] # Parse chapters in Book One chapter_re = re.compile(r'\n\nCHAPTER\s+([IVXLC]+)\s*\n') chapter_matches = list(chapter_re.finditer(book_one)) chapters = {} for i, cm in enumerate(chapter_matches): ch_num = roman_to_int(cm.group(1).strip()) ch_start = cm.end() ch_end = chapter_matches[i+1].start() if i+1 < len(chapter_matches) else len(book_one) chapters[ch_num] = extract_words(book_one[ch_start:ch_end]) # Treasure coordinates: first number = chapter, rest = word positions treasure = [ [1, 71, 12, 21], [1, 11, 15, 18], [5, 10, 55, 1, 47], [2, 64, 11], [4, 36, 65], [8, 70, 8], [10, 26, 28], [1, 6, 11] ] result = '' for line in treasure: ch = line[0] for p in line[1:]: word = chapters[ch][p - 1] # 1-indexed result += word[0] print(f"Ch{ch}:w{p} = '{word}' -> '{word[0]}'") print(f"\nDecoded: {result}") print(f"Flag: CODEBY{{{result[6:].lower()}}}") # Output: CODEBY{REDACTED}
How to obtain the key text
bash read-only • copy allowedcurl -o war_and_peace.txt https://www.gutenberg.org/cache/epub/2600/pg2600.txt
Pitfalls
- Smart quotes (U+2019): Gutenberg texts use Unicode right single quotation marks for apostrophes. If not handled, contractions like "don't" split into two words, shifting all word indices.
- Scope of the book: Only Book One chapters are used, not the entire novel. The chapter numbers (1-10 in the Treasure file) correspond to Book One's chapters.
- The Advice file is NOT the key: It's a thematic red herring styled after the Beale papers advisory letter. The actual key text is War and Peace.
- Correct translation: Must use the Maude translation specifically (Gutenberg #2600), not other translations, as word positions are edition-specific.
Related Challenge
"Сокровище 2" (Treasure 2) from the same CTF uses the same book cipher concept but with "Eloquent JavaScript" PDF and a (page, line, character) coordinate format instead of (chapter, word) format.