← Back to Writeups
CUSTOMMediumCrypto

Сокровище (Treasure)

XESXOR9/2/20266 min read
#crypto#custom#medium#book_cipher_decryption#chapter_word_indexing#first_letter_extraction#unicode_smart_quote_handling

Сокровище (Treasure)

Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: book_cipher_decryption, chapter_word_indexing, first_letter_extraction, unicode_smart_quote_handling

Summary

Walkthrough of the CUSTOM Crypto Сокровище (Treasure). 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 B

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.zip containing:
    • 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 Advice file 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

LineChapterWord positionsWords foundLetters
1Ch.I71, 12, 21call, of, don'tc, o, d
2Ch.I11, 15, 18estates, But, youe, B, y
3Ch.V10, 55, 1, 47the, head, And, nationst, h, A, n
4Ch.II64, 11known, societyk, s
5Ch.IV36, 65bored, roomb, r
6Ch.VIII70, 8of, begino, b
7Ch.X26, 28evening, Annae, A
8Ch.I6, 11Lucca, estatesL, 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
#!/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
curl -o war_and_peace.txt https://www.gutenberg.org/cache/epub/2600/pg2600.txt

Pitfalls

  1. 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.
  2. 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.
  3. 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.
  4. 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. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering book_cipher_decryption, chapter_word_indexing, first_letter_extraction, unicode_smart_quote_handling was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-05 • CUSTOM • Сокровище (Treasure) • Difficulty: Medium