Challenge / Pwn

Execute

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

EasyPublished 2025-03-18Sanitized local writeup

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.

Execute sanitized attack graph

Walkthrough flow

01

Binary triage

02

Memory primitive

03

Control-flow hijack

04

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.

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.

  • 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:

c
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:

bash
python3 Pwn/Execute/solve/solve.py

The 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

FileSizeSHA256TypeNotes
files/a12c73a8-fd5f-49c1-b662-33926850972c.zip4478<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 4 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T09:50:40Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T09:50:40Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T09:50:40Zhypothesis recordedhypothesis-board.mdLocal-first pwn analysis of provided binary, then adapt exploit to remote service at <TARGET>:32249.MediumExtract 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:36Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-09T09:52:36Zcheckpoint recordedanalysis/checkpoint-analysis-20260609T095236215160Z-f52546e9.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-09T09:53:25ZRAG queryanalysis/rag/rag-query-20260609T095314115848Z-e8251f27.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-09T09:54:24ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-09T09:55:17Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-09T09:55:17Zevaluatoranalysis/evaluator-20260609T095517093596Z-5704f576.mdProceedHighRun reproducible socket solver against <TARGET>:32249 and capture flag output.
2026-06-09T09:56:29Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-09T09:57:03Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The archive contains execute, execute.c, and a local placeholder flag.txt.
  • execute.c reads up to 60 bytes into buf[62], checks the read bytes against a blacklist, and then executes buf as 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 read syscall.
  • 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:

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

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

Closed Branches

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

FileSizeSHA256TypeNotes
files/a12c73a8-fd5f-49c1-b662-33926850972c.zip4478<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 4 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T09:50:40Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T09:50:40Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T09:50:40Zhypothesis recordedhypothesis-board.mdLocal-first pwn analysis of provided binary, then adapt exploit to remote service at <TARGET>:32249.MediumExtract 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:36Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-09T09:52:36Zcheckpoint recordedanalysis/checkpoint-analysis-20260609T095236215160Z-f52546e9.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-09T09:53:25ZRAG queryanalysis/rag/rag-query-20260609T095314115848Z-e8251f27.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-09T09:54:24ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-09T09:55:17Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-09T09: <REDACTED>
2026-06-09T09: <REDACTED>
2026-06-09T09:57:03Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The archive contains execute, execute.c, and a local placeholder flag.txt.
  • execute.c reads up to 60 bytes into buf[62], checks the read bytes against a blacklist, and then executes buf as 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 read syscall.
  • 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:

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