Execute
Execute is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Execute attack path
Execute 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 Pwn evidence, validation, and reusable operator lessons.
Walkthrough flow
Binary triage
Memory primitive
Control-flow hijack
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.
- Pwn/Execute/writeup.md
- htb-challenge/Pwn/Execute/notes.md
- htb-challenge/Pwn/Execute/memory-summary.md
- htb-challenge/Pwn/Execute/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Pwn__Execute__memory-summary.md.58a21e2336.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Pwn__Execute__notes.md.9187278499.md
Technical Walkthrough
Writeup
Challenge
- Name: Execute
- Category: Pwn
- Difficulty: Easy
- Mode: hybrid
Summary
The binary intentionally executes user input from the stack after filtering a blacklist of raw bytes. A direct /bin/sh or flag.txt shellcode is blocked by the blacklist, so the exploit uses a clean stage-one loader that passes validation, reads an unrestricted second-stage payload, and jumps to it. The second stage opens, reads, and writes flag.txt from the remote service.
Artifact Inventory
files/extracted/pwn_execute/execute.c: provided vulnerable source.files/extracted/pwn_execute/execute: Linux x64 PIE executable.files/extracted/pwn_execute/flag.txt: local placeholder flag file.- Remote service:
<TARGET>:32249.
Analysis
The source in execute.c is the important artifact:
char buf[62];
char blacklist[] = "\x3b\x54\x62\x69\x6e\x73\x68\xf6\xd2\xc0\x5f\xc9\x66\x6c\x61\x67";
int size = read(0, buf, 60);
if(!check(blacklist, buf, size, strlen(blacklist))) {
exit(1337);
}
((void (*)()) buf)();The compile comment includes -z execstack, and the source jumps directly into buf. The blacklist blocks literal shell and flag strings, plus some common shellcode bytes. The bypass is to make the first checked payload only a small loader:
read(0, rsp, 0x7f)jmp rsp
The validated loader is 15 bytes long and has no intersection with the blacklist; see analysis/stage1-badchar-check.txt.
To avoid TCP coalescing problems, the solver sends exactly 60 bytes for the first read: the 15-byte stage one padded with allowed NOP bytes. The unchecked second stage is appended after those 60 bytes and is consumed by the stage-one read.
The second stage performs direct Linux x64 ORW:
- open
flag.txt - read into the stack
- write the result to stdout
- exit
Solve
Run:
python3 Pwn/Execute/solve/solve.pyThe solver writes:
- raw flag candidate:
loot/flag-candidate.txt - raw remote output:
loot/remote-output.bin - sanitized execution summary:
analysis/remote-solve-summary.json
The harness captured the final flag into loot/flag.txt.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- When a program jumps to a stack buffer after badchar filtering, avoid fighting the filter with a full payload. Use a tiny clean loader and move unrestricted logic into stage two.
- For socket-backed
read(0, buf, 60), sending exactly 60 checked bytes before stage two makes the split deterministic. - Keep remote exploit scripts dependency-free where possible; this solve does not require
pwntools.
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: Execute
- Category: Pwn
- Difficulty: Easy
- Mode: hybrid
- Remote instance: <TARGET>:32249
- Start time: 2026-06-09T09:50:40Z
- 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/a12c73a8-fd5f-49c1-b662-33926850972c.zip | 4478 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 4 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-09T09:50:40Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-09T09:50:40Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-09T09:50:40Z | hypothesis recorded | hypothesis-board.md | Local-first pwn analysis of provided binary, then adapt exploit to remote service at <TARGET>:32249. | Medium | Extract the archive, identify binary protections and behavior, run locally to find input constraints/crash/execution path, then test minimal exploit remotely. |
| 2026-06-09T09:52:36Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-09T09:52:36Z | checkpoint recorded | analysis/checkpoint-analysis-20260609T095236215160Z-f52546e9.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-09T09:53:25Z | RAG query | analysis/rag/rag-query-20260609T095314115848Z-e8251f27.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-09T09:54:24Z | RAG record | analysis/rag-records.md | Retrieved memory tagged MISSING | Medium | Validate or reject with live evidence |
| 2026-06-09T09:55:17Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-09T09:55:17Z | evaluator | analysis/evaluator-20260609T095517093596Z-5704f576.md | Proceed | High | Run reproducible socket solver against <TARGET>:32249 and capture flag output. |
| 2026-06-09T09:56:29Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-09T09:57:03Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The archive contains
execute,execute.c, and a local placeholderflag.txt. execute.creads up to 60 bytes intobuf[62], checks the read bytes against a blacklist, and then executesbufas code.- The compile comment uses
-z execstack, matching the intended stack-shellcode path. - The blacklist blocks literal bytes for
;Tbinsh,flag, and several opcode bytes:3b 54 62 69 6e 73 68 f6 d2 c0 5f c9 66 6c 61 67. - A 15-byte x64 first-stage loader was built and validated with no blacklist-byte intersection:
analysis/stage1-badchar-check.txt. - Planned exploit: send exactly 60 checked bytes as stage one plus allowed NOP padding, then leave an unrestricted ORW second stage queued for the stage-one
readsyscall. - Remote solve succeeded with the direct ORW second stage on the first attempt:
analysis/remote-solve-summary.json. - The harness captured the 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: Pwn
- Challenge: Execute
- 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.
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 | Local-first pwn analysis of provided binary, then adapt exploit to remote service at <TARGET>:32249. | Challenge provides a ZIP plus remote host:port; category is Pwn and scenario hints at feeding input to code. | Extract the archive, identify binary protections and behavior, run locally to find input constraints/crash/execution path, then test minimal exploit remotely. | 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: Pwn
- Challenge: Execute
- 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.
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: Execute
- Category: Pwn
- Difficulty: Easy
- Mode: hybrid
- Remote instance: <TARGET>:32249
- Start time: 2026-06-09T09:50:40Z
- 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/a12c73a8-fd5f-49c1-b662-33926850972c.zip | 4478 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 4 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-09T09:50:40Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-09T09:50:40Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-09T09:50:40Z | hypothesis recorded | hypothesis-board.md | Local-first pwn analysis of provided binary, then adapt exploit to remote service at <TARGET>:32249. | Medium | Extract the archive, identify binary protections and behavior, run locally to find input constraints/crash/execution path, then test minimal exploit remotely. |
| 2026-06-09T09:52:36Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-09T09:52:36Z | checkpoint recorded | analysis/checkpoint-analysis-20260609T095236215160Z-f52546e9.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-09T09:53:25Z | RAG query | analysis/rag/rag-query-20260609T095314115848Z-e8251f27.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-09T09:54:24Z | RAG record | analysis/rag-records.md | Retrieved memory tagged MISSING | Medium | Validate or reject with live evidence |
| 2026-06-09T09:55:17Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-09T09: <REDACTED> | |||||
| 2026-06-09T09: <REDACTED> | |||||
| 2026-06-09T09:57:03Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The archive contains
execute,execute.c, and a local placeholderflag.txt. execute.creads up to 60 bytes intobuf[62], checks the read bytes against a blacklist, and then executesbufas code.- The compile comment uses
-z execstack, matching the intended stack-shellcode path. - The blacklist blocks literal bytes for
;Tbinsh,flag, and several opcode bytes: <REDACTED> - A 15-byte x64 first-stage loader was built and validated with no blacklist-byte intersection:
analysis/stage1-badchar-check.txt. - Planned exploit: send exactly 60 checked bytes as stage one plus allowed NOP padding, then leave an unrestricted ORW second stage queued for the stage-one
readsyscall. - Remote solve succeeded with the direct ORW second stage on the first attempt:
analysis/remote-solve-summary.json. - The harness captured the 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 the challenge as a small system with one rule that matters more than the rest. The solve is finding that rule, validating it, and using it carefully enough to reach the final proof.
For Execute, 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.