Bookworm
Bookworm
Platform: spbctf | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: book_cipher_decryption, page_line_character_indexing, pdf_text_extraction
Summary
Task: Decrypt a book cipher using a PDF book and coordinate file with page-line-character format. Solution: Extract text from PDF with PyMuPDF, skip page numbers and chapter headers, then retrieve characters at specified positions.
Bookworm - Crypto Kids 20 (forkbomb.ru)
Description
"This book can tell you secret if you'll use that file to read it"
Given:
- Book: "Do Androids Dream of Electric Sheep?" by Philip K. Dick (PDF, 111 pages)
- Cipher file:
bookworm.txtwith 17 lines inpage - line - character_positionformat
Contents of bookworm.txt:
71 - 15 - 12
79 - 12 - 49
43 - 8 - 63
89 - 24 - 8
13 - 26 - 27
22 - 6 - 54
34 - 8 - 51
58 - 7 - 50
41 - 15 - 65
11 - 19 - 23
101 - 9 - 85
33 - 11 - 62
94 - 14 - 78
69 - 16 - 12
37 - 13 - 36
89 - 14 - 51
95 - 22 - 37
Analysis
This is a classic book cipher in page-line-character format:
- Each line points to a specific character in the book
- Format:
page - line - character_position - 17 coordinates = 17 flag characters
PDF extraction specifics:
- PyMuPDF (fitz) extracts text with line breaks
- First line of each page is the page number (needs to be skipped)
- Pages with chapter beginnings have an additional header line (ONE, TWO, ..., TWENTY)
- Paragraph indentation (leading whitespace) needs to be removed before counting character position
Solution
python read-only • copy allowed#!/usr/bin/env python3 """ Book cipher solver for Crypto Kids 20 - Bookworm Uses PyMuPDF (fitz) for PDF text extraction """ import fitz # PyMuPDF # Chapter headers that appear on some pages CHAPTER_HEADERS = [ "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN", "TWENTY" ] def extract_character(pdf_path, page_num, line_num, char_pos): """ Extract a single character from PDF using page-line-character coordinates. Args: pdf_path: Path to PDF file page_num: 1-indexed page number line_num: 1-indexed line number (after skipping page number header) char_pos: 1-indexed character position (after stripping leading whitespace) Returns: The character at the specified position """ doc = fitz.open(pdf_path) # PDF pages are 0-indexed page = doc[page_num - 1] text = page.get_text() lines = text.split('\n') # Skip the page number header (first line) lines = lines[1:] # Check if first line is a chapter header and skip it if lines and lines[0].strip() in CHAPTER_HEADERS: lines = lines[1:] # Get the target line (1-indexed) target_line = lines[line_num - 1] # Strip leading whitespace before counting character position target_line = target_line.lstrip() # Get character at position (1-indexed) char = target_line[char_pos - 1] doc.close() return char def solve_bookworm(pdf_path, cipher_file): """ Solve the book cipher by extracting characters from PDF. """ # Parse cipher file coordinates = [] with open(cipher_file, 'r') as f: for line in f: parts = line.strip().split(' - ') if len(parts) == 3: page = int(parts[0]) line_num = int(parts[1]) char_pos = int(parts[2]) coordinates.append((page, line_num, char_pos)) # Extract characters flag = "" for page, line_num, char_pos in coordinates: char = extract_character(pdf_path, page, line_num, char_pos) flag += char print(f"Page {page:3d}, Line {line_num:2d}, Char {char_pos:2d} -> '{char}'") return flag if __name__ == "__main__": pdf_path = "do_androids_dream.pdf" cipher_file = "bookworm.txt" flag = solve_bookworm(pdf_path, cipher_file) print(f"\nFlag: {flag}")
Step-by-step execution:
- Open the PDF using PyMuPDF
- For each coordinate (page, line, char):
- Extract the page text
- Skip the first line (page number)
- If the page starts a chapter - skip the chapter header
- Remove leading whitespace from the target line
- Extract the character by position (1-indexed)
- Concatenate all 17 characters
Result: REDACTED (spbctf + sci-fi is good)
Pitfalls
- PDF text extraction: Different tools (PyMuPDF, pdftotext, pdfplumber) produce different line breaks
- Page headers: Page numbers and chapter headers need to be skipped
- Whitespace: Paragraph indentation affects character position counting
- Indexing: Important to understand whether 0-indexed or 1-indexed numbering is used