BabyEncryption
BabyEncryption is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
BabyEncryption attack path
BabyEncryption is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Objective
Challenge walkthrough focused on Crypto evidence, validation, and reusable operator lessons.
Walkthrough flow
Challenge parameters
Weak assumption
Recovered secret state
Proof captured
Source coverage
High source coverage
Status: complete. This article is generated from 6 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
High confidence: the page is reconstructed from a primary walkthrough plus multiple supporting notes or evidence sources. Treat the chain as source-backed, while still checking the listed source files for sensitive values.
- Crypto/BabyEncryption/writeup.md
- htb-challenge/Crypto/BabyEncryption/notes.md
- htb-challenge/Crypto/BabyEncryption/memory-summary.md
- htb-challenge/Crypto/BabyEncryption/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__BabyEncryption__memory-summary.md.446a149bff.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__BabyEncryption__notes.md.58cac7c041.md
Technical Walkthrough
Writeup
Challenge
- Name: BabyEncryption
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
Summary
This challenge is a direct byte-wise affine cipher. The source file provides the exact encryption rule, so the solve is just modular inversion plus hex decoding.
Artifact Inventory
The challenge consists of two local files:
files/extracted/chall.py: the encryption sourcefiles/extracted/msg.enc: the ciphertext, stored as ASCII hex
analysis/artifact-inventory.json records the hashes and file metadata.
Analysis
files/extracted/chall.py defines a per-byte transform:
c = (123 * m + 18) % 256where m is a plaintext byte and c is the ciphertext byte.
This is an affine transformation over integers modulo 256. Since gcd(123, 256) = 1, the multiplier is invertible. The inverse of 123 mod 256 is 179, so each byte decrypts as:
m = 179 * (c - 18) % 256files/extracted/msg.enc is not raw bytes; it is a hex string. The ciphertext therefore has to be decoded with bytes.fromhex(...) before applying the inverse transform byte by byte.
Solve
Run:
python3 solve/solve.pyThe solver:
- reads
files/extracted/msg.enc - hex-decodes the ciphertext
- applies the inverse affine transform to each byte
- prints the recovered plaintext
The raw flag was then captured into loot/flag.txt with:
cd <local workspace>
python3 scripts/challenge_harness.py capture-flag Crypto/BabyEncryption --from analysis/flag-candidate.txtFlag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- If the source gives you a linear transform directly, derive the inverse first instead of reaching for brute force.
- Byte-wise affine ciphers over modulus
256are trivial to reverse whenever the multiplier is coprime with256.
Source-Backed Dossier
The sections below are merged from companion Markdown notes for the same case. They are rendered after sanitization so the article stays precise without publishing raw flags, credentials, or target-specific secrets.
Notes
Scope
- Challenge: BabyEncryption
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-07T15:52:52Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c7376-5639-45bb-9a52-e8d8649e9954.zip | 631 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=deflate | zip entries: 2 shown in artifact inventory JSON |
files/extracted/chall.py | 234 | <hash redacted> | Python script text executable, ASCII text | |
files/extracted/msg.enc | 160 | <hash redacted> | ASCII text, with no line terminators |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T15:52:52Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T15:53:12Z | artifact inventory | analysis/artifact-inventory.json | 3 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T15:53:12Z | hypothesis recorded | hypothesis-board.md | Reverse chall.py encryption formula and apply the inverse transform to msg.enc to recover the plaintext flag. | High | Read chall.py, identify byte-wise transformation, then implement inverse in solve/solve.py. |
| 2026-06-07T15:53:30Z | research skip | analysis/research/research-skip.md | Research intentionally skipped with recorded reason | Medium | Gate before exploit |
| 2026-06-07T15:53:30Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260607T155330690608Z-3f359780.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-07T15:54:51Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-07T15:56:08Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
chall.pyimplements a byte-wise affine cipher: multiply by123, add18, then reduce modulo256.msg.encstores ciphertext as ASCII hex, so the first decode step isbytes.fromhex(...).- Because
gcd(123, 256) = 1, the modular inverse exists and is179, giving decryption formulam = 179 * (c - 18) mod 256. - The plaintext is recoverable offline with a short deterministic script; no brute force or external research is needed.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: BabyEncryption
- Difficulty: Very Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- Requires user approval before ingestion: yes
Hypothesis Board
Keep no more than 3 active hypotheses on Easy/Medium and 5 on Hard unless the user explicitly asks for breadth.
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|---|---|---|---|---|---|
| 1 | Reverse chall.py encryption formula and apply the inverse transform to msg.enc to recover the plaintext flag. | Archive contains chall.py and msg.enc only; challenge title is BabyEncryption and scenario asks to decrypt a confidential message. | Read chall.py, identify byte-wise transformation, then implement inverse in solve/solve.py. | High | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Memory Summary
approval_required: true
Sanitized Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: BabyEncryption
- Difficulty: Very Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: BabyEncryption
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-07T15:52:52Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c7376-5639-45bb-9a52-e8d8649e9954.zip | 631 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=deflate | zip entries: 2 shown in artifact inventory JSON |
files/extracted/chall.py | 234 | <hash redacted> | Python script text executable, ASCII text | |
files/extracted/msg.enc | 160 | <hash redacted> | ASCII text, with no line terminators |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T15:52:52Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T15:53:12Z | artifact inventory | analysis/artifact-inventory.json | 3 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T15: <REDACTED>, identify byte-wise transformation, then implement inverse in solve/solve.py. | |||||
| 2026-06-07T15:53:30Z | research skip | analysis/research/research-skip.md | Research intentionally skipped with recorded reason | Medium | Gate before exploit |
| 2026-06-07T15:53:30Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260607T155330690608Z-3f359780.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-07T15: <REDACTED> | |||||
| 2026-06-07T15:56:08Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
chall.pyimplements a byte-wise affine cipher: multiply by123, add18, then reduce modulo256.msg.encstores ciphertext as ASCII hex, so the first decode step isbytes.fromhex(...).- Because
gcd(123, 256) = 1, the modular inverse exists and is179, giving decryption formulam = 179 * (c - 18) mod 256. - The plaintext is recoverable offline with a short deterministic script; no brute force or external research is needed.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Technical analogy
How to remember this solve
Think of the challenge like a locked box where the lock is mathematical but slightly flawed. The goal is not to smash the box; it is to notice which part of the lock repeats, leaks, or trusts the wrong assumption.
For BabyEncryption, keep the mental model simple: identify the trusted assumption, prove it with the smallest safe test, then automate or repeat only the part that directly leads to the flag.