PINSMITH
PINSMITH is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
PINSMITH attack path
PINSMITH 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 Coding evidence, validation, and reusable operator lessons.
Walkthrough flow
Fingerprinted the remote as the standard HTB Coding...
Captured the prompt and identified a bounded PIN...
Implemented left-to-right DFS over the template.
Tried wildcard digits from 0 through 9 in order to...
Pruned any branch where the current digit equals the...
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.
- Coding/PINSMITH/writeup.md
- htb-challenge/Coding/PINSMITH/notes.md
- htb-challenge/Coding/PINSMITH/memory-summary.md
- htb-challenge/Coding/PINSMITH/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__PINSMITH__memory-summary.md.59246f3daa.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__PINSMITH__notes.md.d5415af3d4.md
Technical Walkthrough
Writeup
Challenge
- Name: PINSMITH
- Category: Coding
- Difficulty: Easy
- Mode: remote
Summary
PINSMITH is a remote HTB Coding runner. The prompt gives a PIN template containing fixed digits and * wildcards. The task is to enumerate every valid PIN matching the template, with no adjacent equal digits, one PIN per line, in lexicographic order.
Artifact Inventory
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
analysis/remote/root-http.txt: captured the full prompt and/runfrontend.analysis/remote/prompts.js: captured the default language templates.analysis/remote/initial-nc-probe.txt: confirmed the port accepts TCP, but HTTP is the useful runner interface.solve/solution.py: submitted enumeration solution.solve/solve.py: reproducible/runsubmitter.analysis/remote/run-response.json: saved successful runner response.
Analysis
The prompt states that known digits are fixed, unknown positions are represented by *, and adjacent digits cannot be equal. Since output must be lexicographically sorted, the clean approach is a left-to-right DFS that tries candidate digits in ascending order.
At each position:
- if the template character is fixed, keep it only if it does not equal the previous chosen digit
- if the character is
*, try0through9, skipping the previous chosen digit - when the end is reached, emit the built PIN
The PIN length is at most 10, so output generation is bounded and straightforward in Python.
Solve
The submitted code is in solve/solution.py. It reads one template string from stdin, performs DFS/backtracking, and prints each valid PIN on its own line. Testing against the visible sample *23 produced the exact expected output.
The submitter in solve/solve.py posts the solution to /run as Python, saves the raw JSON response to analysis/remote/run-response.json, and writes any returned flag candidate to loot/flag-candidate.txt. The harness then validates and stores the flag in loot/flag.txt.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- Generating outputs in lexicographic order is easiest when the DFS tries characters in sorted order.
- Constraints were small enough for direct generation; no dynamic programming was necessary.
- Always enforce adjacency constraints across both fixed and generated digits.
- Save the
/runresponse for debugging hidden test failures.
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: PINSMITH
- Category: Coding
- Difficulty: Easy
- Mode: remote
- Remote instance: <TARGET>:30521
- Start time: 2026-06-07T23:50:49Z
- 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 |
|---|---|---|---|---|
| — | 0 | — | remote-only or no provided files | No local artifacts found under files/ |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T23:50:49Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T23:51:00Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T23:51:01Z | hypothesis recorded | hypothesis-board.md | Remote Coding service likely exposes an HTTP runner; identify exact PIN reconstruction input/output before submission. | Medium | Probe HTTP root, inspect prompt and JavaScript, then implement the stated algorithm. |
| 2026-06-07T23:51:13Z | checkpoint recorded | analysis/checkpoint-triage-20260607T235113423246Z-fadf7814.md | Checkpoint for TRIAGE | High | Use checkpoint to drive next decision |
| 2026-06-07T23:51:13Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T23:52:02Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T23:52:02Z | hypothesis recorded | hypothesis-board.md | Submit lexicographic DFS solution for PIN templates with '*' wildcards and no adjacent equal digits. | Medium | Run solution against sample, then submit through /run and capture flag if all tests pass. |
| 2026-06-07T23:52:11Z | evaluator | analysis/evaluator-20260607T235211401623Z-fe593794.md | Proceed | High | Run solve/solve.py, capture flag through harness, then complete if successful. |
| 2026-06-07T23:52:24Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-07T23:53:04Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- Remote service is the standard HTB Coding HTTP runner.
- Useful endpoint is
POST /run, as shown inanalysis/remote/root-http.txt. - The challenge is a bounded wildcard PIN enumeration problem.
*positions are expanded with digits0through9.- No generated or fixed digit may equal the immediately previous digit.
- Lexicographic order is preserved by left-to-right DFS with ascending digit order.
solve/solution.pymatched the visible sample and passed the remote runner.- The harness captured the validated flag into
loot/flag.txt.
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: Coding
- Challenge: PINSMITH
- Difficulty: Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
- Fingerprinted the remote as the standard HTB Coding HTTP runner.
- Captured the prompt and identified a bounded PIN wildcard enumeration problem.
- Implemented left-to-right DFS over the template.
- Tried wildcard digits from
0through9in order to preserve lexicographic output. - Pruned any branch where the current digit equals the previous chosen digit.
- Submitted the Python solution through
/runand captured the returned flag through the harness.
Reusable Lessons
- For lexicographic generation, iterate candidates in lexicographic order during DFS rather than generating then sorting.
- Apply adjacency constraints across fixed/template boundaries as well as wildcard choices.
- For small bounded combinatorics tasks, direct generation is often simpler and safer than over-optimizing.
Dead Ends
- Raw TCP was not the useful interface; HTTP
/runwas the correct runner path. - Numeric sorting was not used because the output requirement is lexicographic.
Tool Quirks
- The frontend JavaScript posts JSON to
/runwith fieldscodeandlanguage. - The runner returns JSON; successful responses can contain the flag inside the response body.
Evidence Paths
analysis/remote/root-http.txtanalysis/remote/prompts.jsanalysis/remote/run-response.jsonsolve/solution.pysolve/solve.py
Ingestion Decision
- Proposed for LightRAG: yes
- 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 | Remote Coding service likely exposes an HTTP runner; identify exact PIN reconstruction input/output before submission. | Challenge provides remote host <TARGET>:30521 and a partial numeric PIN scenario. | Probe HTTP root, inspect prompt and JavaScript, then implement the stated algorithm. | Medium | Active | |
| 1 | Submit lexicographic DFS solution for PIN templates with '*' wildcards and no adjacent equal digits. | Problem statement in analysis/remote/root-http.txt specifies fixed digits, wildcard positions, no adjacent repeats, and lexicographic output. | Run solution against sample, then submit through /run and capture flag if all tests pass. | Medium | 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: Coding
- Challenge: PINSMITH
- Difficulty: Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
- Fingerprinted the remote as the standard HTB Coding HTTP runner.
- Captured the prompt and identified a bounded PIN wildcard enumeration problem.
- Implemented left-to-right DFS over the template.
- Tried wildcard digits from
0through9in order to preserve lexicographic output. - Pruned any branch where the current digit equals the previous chosen digit.
- Submitted the Python solution through
/runand captured the returned flag through the harness.
Reusable Lessons
- For lexicographic generation, iterate candidates in lexicographic order during DFS rather than generating then sorting.
- Apply adjacency constraints across fixed/template boundaries as well as wildcard choices.
- For small bounded combinatorics tasks, direct generation is often simpler and safer than over-optimizing.
Dead Ends
- Raw TCP was not the useful interface; HTTP
/runwas the correct runner path. - Numeric sorting was not used because the output requirement is lexicographic.
Tool Quirks
- The frontend JavaScript posts JSON to
/runwith fieldscodeandlanguage. - The runner returns JSON; successful responses can contain the flag inside the response body.
Evidence Paths
analysis/remote/root-http.txtanalysis/remote/prompts.jsanalysis/remote/run-response.jsonsolve/solution.pysolve/solve.py
Ingestion Decision
- Proposed for LightRAG: yes
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: PINSMITH
- Category: Coding
- Difficulty: Easy
- Mode: remote
- Remote instance: <TARGET>:30521
- Start time: 2026-06-07T23:50:49Z
- 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 |
|---|---|---|---|---|
| — | 0 | — | remote-only or no provided files | No local artifacts found under files/ |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T23:50:49Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T23:51:00Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T23:51:01Z | hypothesis recorded | hypothesis-board.md | Remote Coding service likely exposes an HTTP runner; identify exact PIN reconstruction input/output before submission. | Medium | Probe HTTP root, inspect prompt and JavaScript, then implement the stated algorithm. |
| 2026-06-07T23:51:13Z | checkpoint recorded | analysis/checkpoint-triage-20260607T235113423246Z-fadf7814.md | Checkpoint for TRIAGE | High | Use checkpoint to drive next decision |
| 2026-06-07T23:51:13Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T23:52:02Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T23: <REDACTED>, then submit through /run and capture flag if all tests pass. | |||||
| 2026-06-07T23: <REDACTED>, capture flag through harness, then complete if successful. | |||||
| 2026-06-07T23: <REDACTED> | |||||
| 2026-06-07T23:53:04Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- Remote service is the standard HTB Coding HTTP runner.
- Useful endpoint is
POST /run, as shown inanalysis/remote/root-http.txt. - The challenge is a bounded wildcard PIN enumeration problem.
*positions are expanded with digits0through9.- No generated or fixed digit may equal the immediately previous digit.
- Lexicographic order is preserved by left-to-right DFS with ascending digit order.
solve/solution.pymatched the visible sample and passed the remote runner.- The harness captured the validated flag into
loot/flag.txt.
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 it like turning a word problem into a repeatable calculator. Once the rule is clear, the solve is making the computer do the boring part consistently.
For PINSMITH, 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.