Cred Hunter
Cred Hunter is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Cred Hunter attack path
Cred Hunter 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
The remote challenge is an HTTP HTB Coding runner...
The challenge input is a mixed dump of strings...
Employee emails use a lowercase local part structured...
The first name is recovered by removing the final...
A valid pair exists when the first name appears as an...
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/Cred-Hunter/writeup.md
- htb-challenge/Coding/Cred-Hunter/notes.md
- htb-challenge/Coding/Cred-Hunter/memory-summary.md
- htb-challenge/Coding/Cred-Hunter/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Cred-Hunter__memory-summary.md.64f7363650.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Coding__Cred-Hunter__notes.md.f2b7621c95.md
Technical Walkthrough
Writeup
Challenge
- Name: Cred-Hunter
- Category: Coding
- Difficulty: Easy
- Mode: remote
Summary
Cred Hunter is a remote HTB Coding runner. The task is to parse a mixed dump of strings, identify employee email addresses, identify credential-string candidates, then output every valid email/credential pair where the employee's first name appears inside the credential string.
The working solution classifies Cygnus employee emails, extracts the first name from the local part by removing the final last-initial character, checks exact substring matches against non-email credential strings, sorts the unique pairs, and submits the answer through the runner.
Artifact Inventory
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
analysis/remote/root-http.txt: confirms the remote surface is an HTTP Coding runner.analysis/remote/prompts.js: frontend runner JavaScript and challenge prompt source.analysis/remote/initial-nc-probe.txt: confirms this is not a useful raw socket prompt.analysis/remote/run-response.json: saved runner response from the successful/runsubmission.solve/solution.py: submitted Python solution.solve/solve.py: local submitter that postssolution.pyto/runand stores the flag candidate underloot/.
Analysis
The prompt recovered from the remote HTTP page states that the input is a mixed dump of employee emails and credential strings. Employee emails use a lowercase firstname + last_initial local part before an organization domain. Credential strings are entries that do not follow the employee email format.
The important matching rule is exact and case-sensitive: a pair is valid when the extracted first name appears as a substring inside a credential string. The prompt explicitly says uppercase-to-lowercase conversion is not required, so the solution preserves input case.
The output must be sorted lexicographically by email, with multiple credentials for the same email sorted lexicographically. Sorting the unique (email, credential) tuples directly satisfies both requirements.
The implementation treats only lowercase Cygnus-style organization emails as employees. Anything else, including non-matching email-like garbage, remains a credential candidate. This avoids false positives from arbitrary @ strings.
Solve
solve/solution.py performs the challenge logic:
- Read
Nand the following dump strings. - Classify employee emails with a Cygnus-domain regex.
- Extract
first_namefrom the local part by removing the final last-initial character. - Treat every non-matching string as a credential candidate.
- Record every exact first-name substring match.
- Print sorted unique pairs in the required two-column format.
solve/solve.py submits the solution to the remote /run endpoint, saves the full response to analysis/remote/run-response.json, extracts only the flag candidate into loot/flag-candidate.txt, and leaves final validation to the harness.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- For HTB Coding runners, first determine whether the service is HTTP or raw socket. This one exposes
/run. - Preserve the exact matching semantics from the prompt. Here, lowercasing would be an unnecessary mutation.
- Do not classify every
@string as an employee email; use the stated organization email structure. - Keep the flag capture path harness-managed so future writeups can explain the solve without leaking the raw flag.
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: Cred-Hunter
- Category: Coding
- Difficulty: Easy
- Mode: remote
- Remote instance: <TARGET>:30415
- Start time: 2026-06-08T00:26:39Z
- 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-08T00:26:39Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-08T00:26:50Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-08T00:26:50Z | hypothesis recorded | hypothesis-board.md | Remote Coding service likely exposes an HTTP runner; identify exact credential matching input/output before submission. | Medium | Probe HTTP root, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm. |
| 2026-06-08T00:27:13Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-08T00:27:13Z | checkpoint recorded | analysis/checkpoint-triage-20260608T002713220596Z-8b70eb88.md | Checkpoint for TRIAGE | High | Use checkpoint to drive next decision |
| 2026-06-08T00:28:23Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-08T00:28:23Z | hypothesis recorded | hypothesis-board.md | Submit parser that classifies Cygnus employee emails, extracts first names from localpart[:-1], and emits sorted pairs where first name is a credential substring. | Medium | Run solution against sample, then submit through /run and capture flag if all tests pass. |
| 2026-06-08T00:28:33Z | evaluator | analysis/evaluator-20260608T002833848501Z-b0d10d3b.md | Proceed | High | Run solve/solve.py, capture flag through harness, then complete if successful. |
| 2026-06-08T00:28:55Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-08T00:31:36Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The service is a standard HTTP HTB Coding runner, not a useful raw socket prompt.
- The useful execution surface is
/run, which accepts Python code through JSON. - Employee emails are lowercase Cygnus-style addresses where the local part is
firstname + last_initial. - The first name is recovered by removing the final local-part character.
- Credential candidates are non-employee-email strings.
- A valid pair requires an exact case-sensitive first-name substring match.
- The solution prints sorted unique email/credential pairs.
solve/solution.pypassed the runner, and the harness captured the flag intoloot/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: Cred-Hunter
- 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.
- The remote challenge is an HTTP HTB Coding runner with a
/runendpoint. - The challenge input is a mixed dump of strings containing employee emails and credential candidates.
- Employee emails use a lowercase local part structured as
firstname + last_initialand a Cygnus-style company domain. - The first name is recovered by removing the final character from the email local part.
- A valid pair exists when the first name appears as an exact substring inside a credential string.
- Non-employee-email strings are treated as credential candidates.
- Unique
(email, credential)pairs are sorted lexicographically and printed in the required two-column format. - The submitted solution passed the runner and the harness captured the flag under
loot/.
Reusable Lessons
- For Coding challenges, identify the runner interface first. HTTP
/runsubmissions need a local submitter wrapper; raw sockets need a different harness. - Preserve prompt semantics exactly. Here, no case normalization is required.
- Employee-email classification should be stricter than "string contains
@"; non-matching email-like values may be garbage or credential candidates. - Sorting tuple pairs directly is a simple way to satisfy email-first and credential-second ordering.
Dead Ends
- Treating the challenge as a raw socket service was not useful; the service is HTTP.
- Lowercasing credential candidates or first names is unnecessary and could create false matches.
- Treating every
@-containing string as an employee email would risk misclassification.
Tool Quirks
- The frontend JavaScript posts Python code to
/runas JSON with{"code": "...", "language": "python"}. - The successful runner response was stored locally, while the raw flag was captured only through the harness into
loot/.
Evidence Paths
analysis/remote/root-http.txtanalysis/remote/prompts.jsanalysis/remote/initial-nc-probe.txtanalysis/remote/run-response.jsonsolve/solution.pysolve/solve.pyloot/flag.txt
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 credential matching input/output before submission. | Challenge provides remote host <TARGET>:30415 and a credential matching scenario. | Probe HTTP root, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm. | Medium | Active | |
| 1 | Submit parser that classifies Cygnus employee emails, extracts first names from localpart[:-1], and emits sorted pairs where first name is a credential substring. | Problem statement in analysis/remote/root-http.txt specifies first-name matching, exact case, and lexicographic ordering by email/credential. | 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: Cred-Hunter
- 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.
- The remote challenge is an HTTP HTB Coding runner with a
/runendpoint. - The challenge input is a mixed dump of strings containing employee emails and credential candidates.
- Employee emails use a lowercase local part structured as
firstname + last_initialand a Cygnus-style company domain. - The first name is recovered by removing the final character from the email local part.
- A valid pair exists when the first name appears as an exact substring inside a credential string.
- Non-employee-email strings are treated as credential candidates.
- Unique
(email, credential)pairs are sorted lexicographically and printed in the required two-column format. - The submitted solution passed the runner and the harness captured the flag under
loot/.
Reusable Lessons
- For Coding challenges, identify the runner interface first. HTTP
/runsubmissions need a local submitter wrapper; raw sockets need a different harness. - Preserve prompt semantics exactly. Here, no case normalization is required.
- Employee-email classification should be stricter than "string contains
@"; non-matching email-like values may be garbage or credential candidates. - Sorting tuple pairs directly is a simple way to satisfy email-first and credential-second ordering.
Dead Ends
- Treating the challenge as a raw socket service was not useful; the service is HTTP.
- Lowercasing credential candidates or first names is unnecessary and could create false matches.
- Treating every
@-containing string as an employee email would risk misclassification.
Tool Quirks
- The frontend JavaScript posts Python code to
/runas JSON with{"code": "...", "language": "python"}. - The successful runner response was stored locally, while the raw flag was captured only through the harness into
loot/.
Evidence Paths
analysis/remote/root-http.txtanalysis/remote/prompts.jsanalysis/remote/initial-nc-probe.txtanalysis/remote/run-response.jsonsolve/solution.pysolve/solve.pyloot/flag.txt
Ingestion Decision
- Proposed for LightRAG: yes
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: Cred-Hunter
- Category: Coding
- Difficulty: Easy
- Mode: remote
- Remote instance: <TARGET>:30415
- Start time: 2026-06-08T00:26:39Z
- 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-08T00:26:39Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-08T00:26:50Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-08T00: <REDACTED>, inspect prompt and JavaScript, then implement the stated parsing/matching algorithm. | |||||
| 2026-06-08T00:27:13Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-08T00:27:13Z | checkpoint recorded | analysis/checkpoint-triage-20260608T002713220596Z-8b70eb88.md | Checkpoint for TRIAGE | High | Use checkpoint to drive next decision |
| 2026-06-08T00:28:23Z | artifact inventory | analysis/artifact-inventory.json | 0 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-08T00: <REDACTED>, extracts first names from localpart[: <REDACTED>, and emits sorted pairs where first name is a credential substring. | Medium | Run solution against sample, then submit through /run and capture flag if all tests pass. | |||
| 2026-06-08T00: <REDACTED>, capture flag through harness, then complete if successful. | |||||
| 2026-06-08T00: <REDACTED> | |||||
| 2026-06-08T00:31:36Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The service is a standard HTTP HTB Coding runner, not a useful raw socket prompt.
- The useful execution surface is
/run, which accepts Python code through JSON. - Employee emails are lowercase Cygnus-style addresses where the local part is
firstname + last_initial. - The first name is recovered by removing the final local-part character.
- Credential candidates are non-employee-email strings.
- A valid pair requires an exact case-sensitive first-name substring match.
- The solution prints sorted unique email/credential pairs.
solve/solution.pypassed the runner, and the harness captured the flag intoloot/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 Cred Hunter, 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.