Regas Town
Regas Town is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Regas Town attack path
Regas Town 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 Reversing evidence, validation, and reusable operator lessons.
Walkthrough flow
Binary triage
Control-flow recovery
Key logic reconstruction
Proof captured
Source coverage
High source coverage
Status: complete. This article is generated from 4 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.
- Reversing/Regas-Town/writeup.md
- htb-challenge/Reversing/Regas-Town/notes.md
- htb-challenge/Reversing/Regas-Town/memory-summary.md
- htb-challenge/Reversing/Regas-Town/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: Regas-Town
- Category: Reversing
- Difficulty: Medium
- Mode: file
Summary
Rega's Town is a Rust reversing challenge built around regular-expression rules and arithmetic checks over parts of the input. The binary includes debug symbols, so the relevant functions are visible: filter_input, multiply_characters, check_input, and main.
The solve path is static: extract the regex rules from .rodata, recover the fixed string slices and product constants from check_input, apply two hidden index checks in main, and resolve the final product-order collision using the challenge title.
Artifact Inventory
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
files/extracted/dist/rega_town: Rust x86-64 PIE ELF, dynamically linked, with debug info, not stripped.- No remote instance is required for this challenge.
- Main artifacts:
- analysis/source-audit.md
- analysis/disasm-filter_input.txt
- analysis/disasm-check_input.txt
- analysis/disasm-main.txt
- analysis/solver-summary.txt
Analysis
filter_input copies a 9-element Rust &str array from .rodata and compiles each entry with the Rust regex crate. The extracted patterns constrain the flag shape, length, fixed HTB-style wrapping, uppercase positions, underscores, digit count, and several fixed phrase fragments.
multiply_characters maps each character to its Unicode codepoint and multiplies the values as u128.
check_input extracts seven ranges and compares their products:
[4:7][8:11][12:15][16:20][21:23][24:27][28:32]
main then checks two individual characters from the collected Vec<char>, resolving two product collisions. The final remaining collision is between a real word and a transposed spelling; the challenge title selects the real word.
Solve
Run:
python3 solve/solve.pyThe solver enumerates segment candidates from the regex character classes, filters them by the recovered product constants, applies the two hidden index checks, ranks the semantic candidates, and writes the selected HTB-format value to loot/flag-candidate.txt.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- Rust debug symbols can make a large static binary tractable if you focus only on challenge-owned functions.
- Product checks over characters are collision-prone; look for additional disambiguation checks or semantic hints.
- Regex extraction from Rust
&strarrays is more reliable than relying on concatenatedstringsoutput.
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: Regas-Town
- Category: Reversing
- Difficulty: Medium
- Mode: file
- Remote instance: none
- Start time: 2026-06-12T06:02:54Z
- 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/a12c7398-0fcf-4385-8cf4-1e0f90f48ab9.zip | 5159621 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 2 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-12T06:02:54Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-12T06:03:09Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-12T06:06:37Z | hypothesis recorded | hypothesis-board.md | Run the Linux ELF under an amd64 container for behavioral validation | Medium | If needed, run a linux/amd64 container with the binary mounted and feed the derived passphrase |
| 2026-06-12T06:06:37Z | hypothesis recorded | hypothesis-board.md | Recover passphrase by extracting Rust regex constraints and u128 character-product checks | High | Parse the regex array and product constants, enumerate small segment collisions, and select the meaningful flag phrase |
| 2026-06-12T06:07:36Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-12T06:07:36Z | checkpoint recorded | analysis/checkpoint-analysis-20260612T060736849226Z-31ec9b1d.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-12T06:07:38Z | local memory search | analysis/research/local-memory-search-20260612T060738506300Z-6d3bccc7.md | Found 5 safe prior-note result(s) | Medium | Record useful result or skip |
| 2026-06-12T06:08:59Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-12T06:08:59Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-12T06:08:59Z | instrumentation plan | analysis/instrumentation-plan.md | Derive and validate the Rega's Town HTB flag from static Rust binary constraints | High | Stop if the solver finds zero candidates, multiple equally plausible semantic candidates after hidden checks, or if evidence contradicts the extracted constants. |
| 2026-06-12T06:09:15Z | evaluator | analysis/evaluator-20260612T060915125086Z-5a3392e6.md | Proceed | High | Build and run deterministic solver, then capture the candidate with challenge_harness capture-flag. |
| 2026-06-12T06:11:00Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-12T06:12:23Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The binary is a Rust x86-64 ELF with debug symbols and visible
rega_town::*functions. filter_inputvalidates nine Rust regexes stored as a.rodataarray of&str.check_inputslices the candidate into seven fixed ranges and comparesu128products of character codepoints.mainadds two hidden collision breakers: character index 5 must be'0', and index 9 must be'r'.- Product checks are lossy; after hidden checks, the remaining ambiguity is a
Town/Twonproduct-order collision. - The solver chooses the natural challenge-title phrase and stores the HTB-format value only in
loot/.
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: Reversing
- Challenge: Regas-Town
- Difficulty: Medium
- 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 |
|---|---|---|---|---|---|---|
| 2 | Run the Linux ELF under an amd64 container for behavioral validation | local host is macOS arm64 and cannot execute the target ELF natively; Docker client is present | Docker daemon/platform image availability is not guaranteed and static validation may be sufficient | If needed, run a linux/amd64 container with the binary mounted and feed the derived passphrase | Medium | Active |
| 1 | Recover passphrase by extracting Rust regex constraints and u128 character-product checks | strings and filter_input disassembly show nine regexes; check_input disassembly slices fixed ranges and compares multiply_characters outputs to seven constants | Need reproduce the constraints in a solver and validate a candidate against all regexes/products | Parse the regex array and product constants, enumerate small segment collisions, and select the meaningful flag phrase | High | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Technical analogy
How to remember this solve
Think of it like taking apart a small appliance on a workbench. You do not need every screw at once; you trace the control path and rebuild just enough logic to make it reveal the answer.
For Regas Town, 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.