Challenge / Coding

PINSMITH

PINSMITH is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator

EasyPublished 2024-03-07Sanitized local writeup

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.

PINSMITH sanitized attack graph

Walkthrough flow

01

Fingerprinted the remote as the standard HTB Coding...

02

Captured the prompt and identified a bounded PIN...

03

Implemented left-to-right DFS over the template.

04

Tried wildcard digits from 0 through 9 in order to...

05

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.

100% coverage
Evidence verdict

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 /run frontend.
  • 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 /run submitter.
  • 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 *, try 0 through 9, 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 /run response 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

FileSizeSHA256TypeNotes
0remote-only or no provided filesNo local artifacts found under files/

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T23:50:49Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T23:51:00Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:51:01Zhypothesis recordedhypothesis-board.mdRemote Coding service likely exposes an HTTP runner; identify exact PIN reconstruction input/output before submission.MediumProbe HTTP root, inspect prompt and JavaScript, then implement the stated algorithm.
2026-06-07T23:51:13Zcheckpoint recordedanalysis/checkpoint-triage-20260607T235113423246Z-fadf7814.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-07T23:51:13Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T23:52:02Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:52:02Zhypothesis recordedhypothesis-board.mdSubmit lexicographic DFS solution for PIN templates with '*' wildcards and no adjacent equal digits.MediumRun solution against sample, then submit through /run and capture flag if all tests pass.
2026-06-07T23:52:11Zevaluatoranalysis/evaluator-20260607T235211401623Z-fe593794.mdProceedHighRun solve/solve.py, capture flag through harness, then complete if successful.
2026-06-07T23:52:24Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-07T23:53:04Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Remote service is the standard HTB Coding HTTP runner.
  • Useful endpoint is POST /run, as shown in analysis/remote/root-http.txt.
  • The challenge is a bounded wildcard PIN enumeration problem.
  • * positions are expanded with digits 0 through 9.
  • 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.py matched 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:

bash
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.

  1. Fingerprinted the remote as the standard HTB Coding HTTP runner.
  2. Captured the prompt and identified a bounded PIN wildcard enumeration problem.
  3. Implemented left-to-right DFS over the template.
  4. Tried wildcard digits from 0 through 9 in order to preserve lexicographic output.
  5. Pruned any branch where the current digit equals the previous chosen digit.
  6. Submitted the Python solution through /run and 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 /run was the correct runner path.
  • Numeric sorting was not used because the output requirement is lexicographic.

Tool Quirks

  • The frontend JavaScript posts JSON to /run with fields code and language.
  • The runner returns JSON; successful responses can contain the flag inside the response body.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Remote 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.MediumActive
1Submit 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.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit 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.

  1. Fingerprinted the remote as the standard HTB Coding HTTP runner.
  2. Captured the prompt and identified a bounded PIN wildcard enumeration problem.
  3. Implemented left-to-right DFS over the template.
  4. Tried wildcard digits from 0 through 9 in order to preserve lexicographic output.
  5. Pruned any branch where the current digit equals the previous chosen digit.
  6. Submitted the Python solution through /run and 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 /run was the correct runner path.
  • Numeric sorting was not used because the output requirement is lexicographic.

Tool Quirks

  • The frontend JavaScript posts JSON to /run with fields code and language.
  • The runner returns JSON; successful responses can contain the flag inside the response body.

Evidence Paths

  • analysis/remote/root-http.txt
  • analysis/remote/prompts.js
  • analysis/remote/run-response.json
  • solve/solution.py
  • solve/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

FileSizeSHA256TypeNotes
0remote-only or no provided filesNo local artifacts found under files/

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T23:50:49Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T23:51:00Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T23:51:01Zhypothesis recordedhypothesis-board.mdRemote Coding service likely exposes an HTTP runner; identify exact PIN reconstruction input/output before submission.MediumProbe HTTP root, inspect prompt and JavaScript, then implement the stated algorithm.
2026-06-07T23:51:13Zcheckpoint recordedanalysis/checkpoint-triage-20260607T235113423246Z-fadf7814.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-07T23:51:13Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T23:52:02Zartifact inventoryanalysis/artifact-inventory.json0 artifact(s) inventoriedHighBuild 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:04Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Remote service is the standard HTB Coding HTTP runner.
  • Useful endpoint is POST /run, as shown in analysis/remote/root-http.txt.
  • The challenge is a bounded wildcard PIN enumeration problem.
  • * positions are expanded with digits 0 through 9.
  • 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.py matched 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:

bash
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.