Challenge / GamePwn

NoMap3d

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

MediumPublished 2024-08-15Sanitized local writeup

Scenario

NoMap3d attack path

NoMap3d 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 GamePwn evidence, validation, and reusable operator lessons.

NoMap3d sanitized attack graph

Walkthrough flow

01

Extract the file-only GamePwn archive and inspect the...

02

Parse assets.dmp: section type 1 stores player...

03

Use x-major map indexing from the binary: offset =...

04

Render the first byte of each map cell as the...

05

Decode the banner into the HTB-format proof,...

Source coverage

High source coverage

Status: complete. This article is generated from 4 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.

  • GamePwn/NoMap3d/writeup.md
  • htb-challenge/GamePwn/NoMap3d/notes.md
  • htb-challenge/GamePwn/NoMap3d/memory-summary.md
  • htb-challenge/GamePwn/NoMap3d/hypothesis-board.md

Technical Walkthrough

Writeup

Challenge

  • Name: NoMap3d
  • Category: GamePwn
  • Difficulty: Medium
  • Mode: file

Summary

NoMap3d is a file-only GamePwn challenge built around a small native raycaster-style ELF and an assets.dmp blob. The solve path was not runtime patching or manual gameplay. The flag was embedded as a bitmap banner in the map wall/collision plane.

Artifact Inventory

  • files/a12c735f-0ef9-4098-a5bb-56c2f1db0657.zip: original challenge archive.
  • files/extracted/gamepwn_nomap3d/nomap3d: 64-bit Linux PIE ELF, dynamically linked, not stripped.
  • files/extracted/gamepwn_nomap3d/assets.dmp: asset blob containing the player section, map section, skybox, and texture data.

Analysis

The useful symbols in the ELF included load_assets, load_assets_texture, player_init, input, and raycast, which made asset parsing cheaper than dynamic gameplay.

The asset blob starts with a player section and then a map section. The map section has type 2, width 259, height 12, and three bytes per cell. The important implementation detail is that the binary indexes the map as x-major:

text
offset = map_start + (x * height + y) * 3

Using row-major indexing produced misleading output. Rendering the first byte of each x-major cell as the wall/collision plane revealed a readable 7-row bitmap banner inside the maze.

Evidence:

  • analysis/disasm-load-assets.txt
  • analysis/map-index-xrefs.txt
  • analysis/map-decoding.md
  • analysis/map-wall-white.png
  • analysis/map-wall-annotated.png

RAG was checked, but it returned no NoMap3d-specific answer. The solve is based on direct local artifact evidence.

Solve

The reproducible decoder is solve/solve.py.

It performs these checks:

  1. Opens files/extracted/gamepwn_nomap3d/assets.dmp.
  2. Validates the map section header and expected dimensions.
  3. Extracts the x-major wall/collision plane.
  4. Validates invariant glyph shapes from the hidden banner.
  5. Reconstructs the HTB-format flag and writes it to loot/flag-candidate.txt.

The harness accepted the generated candidate and stored the final flag in loot/flag.txt.

One correction was needed after platform submission: the visible wall banner uses a block font, but the exact HTB flag casing is mixed case. The decoder now preserves the intended lowercase glyphs instead of normalizing the whole banner to uppercase.

Flag

Raw flag is stored in loot/flag.txt and intentionally not reproduced here.

Lessons

  • For native GamePwn/raycaster challenges, parse the asset format before trying to play or patch the binary.
  • Map orientation matters. If a map render looks nonsensical, validate how the binary indexes cells before closing the branch.
  • HTB flags are case-sensitive. A readable bitmap phrase can still require exact mixed-case transcription.
  • RAG/community memory can be useful, but for this challenge it was not specific enough; direct artifact evidence was decisive.

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: NoMap3d
  • Category: GamePwn
  • Difficulty: Medium
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-13T02:15:51Z
  • 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/a12c735f-0ef9-4098-a5bb-56c2f1db0657.zip6070285<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 3 shown in artifact inventory JSON
files/extracted/gamepwn_nomap3d/assets.dmp10158080<hash redacted>data
files/extracted/gamepwn_nomap3d/nomap3d22816<hash redacted>ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=<hash redacted>, for GNU/Linux 3.2.0, not stripped

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-13T02:15:51Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-13T02:16:10Zartifact inventoryanalysis/artifact-inventory.json3 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-13T02:16:28Zhypothesis recordedhypothesis-board.mdReverse the native 3D maze/raycaster and assets.dmp to recover the hidden map, exit condition, or encoded flag path; likely solve through asset parsing rather than manual play.MediumRun strings/file/disassembly, parse assets.dmp sections, identify map dimensions/textures/collision bytes, and compare against prior raycaster asset patterns.
2026-06-13T02:16:29Zcheckpoint recordedanalysis/checkpoint-triage-20260613T021629027622Z-3752c3b3.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-13T02:17:44ZRAG queryanalysis/rag/rag-query-20260613T021737525922Z-b4521a03.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-13T02:28:00ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-13T02:28:00Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-13T02:28:00Zinstrumentation plananalysis/instrumentation-plan.mdRecover the NoMap3d flag from the asset map without manual gameplay.HighStop if map dimensions, glyph invariants, or HTB flag format validation fail instead of guessing visually.
2026-06-13T02:28:20Zevaluatoranalysis/evaluator-20260613T022820020322Z-0072e8d9.mdProceedHighRun exploit gate, capture the flag candidate, then complete.
2026-06-13T02:28:20Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-13T02:29:49Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval
2026-06-13T03:37:54Zbranch closedhypothesis-board.mdHTB platform rejected the all-uppercase interpretation; hidden bitmap content was right but exact flag casing was wrong.HighRerank hypotheses
2026-06-13T03:37:54Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-13T03:38:05Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-13T03:38:05Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The ELF is a small native raycaster-style binary with useful exported symbols for asset loading, input, and raycasting.
  • assets.dmp contains a 259 x 12 map section with three bytes per cell.
  • The binary indexes the map x-major, not row-major: (x height + y) 3.
  • Rendering the first map byte as a wall/collision plane reveals a bitmap banner in the maze.
  • solve/solve.py decodes the banner and writes the HTB-format flag candidate into loot/; the harness captured it successfully.

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: GamePwn
  • Challenge: NoMap3d
  • Difficulty: Medium
  • Source workspace: <local workspace>

Validated Solve Chain

Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.

  1. Extract the file-only GamePwn archive and inspect the native ELF symbols before runtime work.
  2. Parse assets.dmp: section type 1 stores player coordinates; section type 2 stores a 259 x 12 map with three bytes per cell.
  3. Use x-major map indexing from the binary: offset = map_start + (x height + y) 3.
  4. Render the first byte of each map cell as the wall/collision plane. Rows 2..8 form a 7-row bitmap banner.
  5. Decode the banner into the HTB-format flag, preserving exact mixed-case glyph intent, and keep the raw flag only in loot/.

Reusable Lessons

  • For raycaster-style GamePwn challenges, asset parsing can be faster and safer than manual play or binary patching.
  • If a rendered map looks wrong, confirm row-major versus column/x-major indexing from code references.
  • Hidden text can be embedded in collision/wall planes rather than texture strings.
  • Case matters for HTB submission; block-font banners may visually look uppercase even when the intended flag has lowercase characters.
  • Treat RAG as advisory; direct asset evidence outranks unrelated retrieved memories.

Dead Ends

  • Row-major map rendering produced misleading/noisy output.
  • OCR over the rendered map was unreliable for leetspeak glyphs; direct bitmap validation was more reliable.
  • The initial all-uppercase transcription was rejected by the platform. Mixed-case transcription fixed the issue.

Tool Quirks

  • Tesseract misread the blocky bitmap font, especially digits and repeated glyphs.
  • Missing Ghidra/rizin/radare2 did not block this solve because exported symbols and objdump were sufficient.

Evidence Paths

  • analysis/artifact-inventory.json
  • analysis/disasm-load-assets.txt
  • analysis/map-index-xrefs.txt
  • analysis/map-decoding.md
  • analysis/map-wall-white.png
  • analysis/map-wall-annotated.png
  • analysis/research/nomap3d-ctfbase-casing.md
  • solve/solve.py
  • loot/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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Reverse the native 3D maze/raycaster and assets.dmp to recover the hidden map, exit condition, or encoded flag path; likely solve through asset parsing rather than manual play.Archive contains a native executable named nomap3d plus assets.dmp, and the scenario says the player is lost without a map.Run strings/file/disassembly, parse assets.dmp sections, identify map dimensions/textures/collision bytes, and compare against prior raycaster asset patterns.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition
all-uppercase wall-bitmap casinganalysis/map-decoding.mdloot/flag-candidate.txtHTB platform rejected the all-uppercase interpretation; hidden bitmap content was right but exact flag casing was wrong.Use direct bitmap evidence plus community writeup only for casing disambiguation, then regenerate loot with mixed-case glyph mapping.

Technical analogy

How to remember this solve

Think of the game like an arcade cabinet with a score counter behind the glass. The solve is finding where the game stores state and reading or changing it at the right moment.

For NoMap3d, 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.