Challenge / GamePwn

NoRadar

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

EasyPublished 2024-08-18Sanitized local writeup

Scenario

NoRadar attack path

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

NoRadar sanitized attack graph

Walkthrough flow

01

Inventory the archive and extract the unstripped...

02

Use symbols and disassembly to identify...

03

Parse the static waypoint table copied from .rodata...

04

Split the coordinate list on (0, 0) sentinels and...

05

Map the rendered glyphs to letters and leetspeak...

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.

  • GamePwn/NoRadar/writeup.md
  • htb-challenge/GamePwn/NoRadar/notes.md
  • htb-challenge/GamePwn/NoRadar/memory-summary.md
  • htb-challenge/GamePwn/NoRadar/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__GamePwn__NoRadar__memory-summary.md.b84ba3d6f7.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__GamePwn__NoRadar__notes.md.a79fb4720b.md

Technical Walkthrough

Writeup

Challenge

  • Name: NoRadar
  • Category: GamePwn
  • Difficulty: Easy
  • Mode: file

Summary

NoRadar is a file-only GamePwn challenge built as a small unstripped Linux SDL game. The flag is not stored as a string and does not require playing the game manually. The moving green cube route is encoded as a static waypoint table in the ELF; when the zero-separated waypoint groups are rendered as 7x7 line glyphs, they spell the flag. The embedded glyph alphabet includes leetspeak digits, so the right-sided E-like glyph must be read as 3, and the A-like glyph must be read as 4.

Artifact Inventory

  • files/a12c736e-81ff-4edc-adda-82bb85a6024b.zip: original HTB archive, preserved unmodified.
  • files/extracted/gamepwn_noradar/noradar: Linux x86-64 PIE SDL ELF, not stripped. Evidence: analysis/file-extracted.txt, analysis/nm.txt.
  • files/extracted/gamepwn_noradar/assets.dmp: custom asset dump with a 350x21 map and textures. Evidence: analysis/assets-parse-summary.txt.
  • Extracted visual aids are under analysis/textures/, analysis/map-col.png, and analysis/waypoint-glyphs.png.

Analysis

The binary imports SDL and SDL_image calls, and symbol names reveal game-specific routines such as load_assets, green_cube1_new, green_cube2_new, green_cube3_new, and green_cube3_update. This made the moving cube logic the highest-value target. Evidence: analysis/strings-noradar.txt, analysis/nm.txt.

assets.dmp is loaded by chunk type. The parser reconstructed chunk type 1 as initial player doubles, type 2 as the column-major map, type 3 as the skybox texture, and type 4 as named textures including htb, floor, and green_cube. Evidence: analysis/assets-parse-summary.txt, analysis/textures/0_htb.png.

The hidden payload is not in those texture pixels. The route table copied by green_cube3_update starts at .rodata address/file offset 0x5060. The routine copies 0x176 qwords, which is 187 coordinate pairs. The pairs use (0, 0) as separators; the non-zero coordinates lie on a 7x7 grid. Rendering each group as connected line segments produces readable glyphs. Some glyphs are intentionally digit-shaped leetspeak, not plain letters. Evidence: analysis/disasm-assets-green-updates.txt, analysis/route-table-summary.txt, analysis/waypoint-glyphs-ascii.txt.

Private CTF LightRAG did not return a matching NoRadar solve pattern, so the solution uses only local binary evidence. Evidence: analysis/research-lightrag-noradar.txt, analysis/research/research-records.md.

Solve

Run:

bash
cd <local workspace>
python3 solve/solve.py --output loot/flag-candidate.txt

The script reads the ELF, extracts the waypoint pairs from offset 0x5060, splits them into glyph groups at (0, 0), draws each group with Bresenham line interpolation on a 7x7 grid, maps each rendered glyph to the correct letter or leetspeak digit, and writes the recovered flag candidate. The harness then validates and stores the final flag:

bash
cd <local workspace>
./scripts/challenge_harness.py capture-flag GamePwn/NoRadar --from loot/flag-candidate.txt

Flag

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

Lessons

  • For small unstripped GamePwn binaries, symbol names can make static analysis faster than runtime game interaction.
  • Named textures can be useful clues, but the actual payload may live in movement/route data rather than pixels.
  • Zero-separated coordinate tables are worth rendering visually before attempting deeper decompilation.

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: NoRadar
  • Category: GamePwn
  • Difficulty: Easy
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-09T11:33:10Z
  • 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/a12c736e-81ff-4edc-adda-82bb85a6024b.zip1786667<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 3 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T11:33:10Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T11:33:38Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T11:35:14Zhypothesis recordedhypothesis-board.mdStatic route extraction from green_cube3_update waypoint tableMediumParse the 189 waypoint pairs from .rodata and derive final/current green cube coordinates; validate against constructor/reset logic.
2026-06-09T11:35:14Zresearch taskanalysis/research/task-20260609T113514483249Z-681c6ef8.mdResearch task created for advisory investigationMediumRecord research output
2026-06-09T11:35:50Zresearch recordanalysis/research/research-records.mdResearch tagged MISSINGMediumValidate against current evidence
2026-06-09T11:40:53Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-09T11:42:31Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval
2026-06-09T11:46:58Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-09T11:48:19Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval
2026-06-09T12:03:05Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-09T12:03:06Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The provided ZIP extracted to gamepwn_noradar/noradar and gamepwn_noradar/assets.dmp; see analysis/unzip.txt.
  • noradar is an unstripped Linux x86-64 SDL ELF with visible functions including green_cube3_update; see analysis/file-extracted.txt and analysis/nm.txt.
  • assets.dmp contains a 350x21 column-major map plus textures named htb, floor, and green_cube; see analysis/assets-parse-summary.txt.
  • The green_cube3_update routine copies a static waypoint table from .rodata at 0x5060; plotting zero-separated 7x7 waypoint groups renders the hidden flag glyphs; see analysis/waypoint-glyphs-ascii.txt and analysis/waypoint-glyphs.png.
  • solve/solve.py reconstructs the glyphs from the ELF. Two glyphs are leetspeak digits rather than letters: the right-sided E-like glyph is 3, and the A-like glyph is 4. The solver writes the corrected HTB-format flag to loot/ for harness capture.

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: NoRadar
  • 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. Inventory the archive and extract the unstripped Linux SDL ELF plus custom assets.dmp.
  2. Use symbols and disassembly to identify green_cube3_update as the moving target logic.
  3. Parse the static waypoint table copied from .rodata into 187 coordinate pairs.
  4. Split the coordinate list on (0, 0) sentinels and render each non-empty group as connected 7x7 line glyphs.
  5. Map the rendered glyphs to letters and leetspeak digits, then capture the corrected HTB-format flag through the harness.

Reusable Lessons

  • In file-only GamePwn challenges, movement paths can encode text even when textures and strings do not contain the flag.
  • For unstripped C/SDL games, start with symbol names and targeted disassembly before heavyweight game execution.
  • Render small coordinate tables as glyphs or paths early; visual encodings are common in easy game/reversing hybrids.
  • Do not normalize glyph text blindly: E-like/right-sided glyphs may be 3, and A-like glyphs may be 4 in leetspeak flags.

Dead Ends

  • The named htb texture was only a branded wall pattern, not the flag.
  • CTF LightRAG did not contain a relevant NoRadar-specific prior solve.

Tool Quirks

  • macOS otool did not parse the Linux ELF; file, strings, nm, and objdump were sufficient.
  • The harness-native RAG query validator rejected broad wording; a manually recorded missing research result was enough because local binary evidence drove the solve.

Evidence Paths

  • analysis/assets-parse-summary.txt
  • analysis/disasm-assets-green-updates.txt
  • analysis/route-table-summary.txt
  • analysis/waypoint-glyphs-ascii.txt
  • analysis/waypoint-glyphs.png
  • 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
1Static route extraction from green_cube3_update waypoint tableUnstripped ELF exposes green_cube3_update and copies a waypoint table from .rodata at 0x5060; scenario asks to track green cube location.Parse the 189 waypoint pairs from .rodata and derive final/current green cube coordinates; validate against constructor/reset logic.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: GamePwn
  • Challenge: NoRadar
  • 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. Inventory the archive and extract the unstripped Linux SDL ELF plus custom assets.dmp.
  2. Use symbols and disassembly to identify green_cube3_update as the moving target logic.
  3. Parse the static waypoint table copied from .rodata into 187 coordinate pairs.
  4. Split the coordinate list on (0, 0) sentinels and render each non-empty group as connected 7x7 line glyphs.
  5. Map the rendered glyphs to letters and leetspeak digits, then capture the corrected HTB-format flag through the harness.

Reusable Lessons

  • In file-only GamePwn challenges, movement paths can encode text even when textures and strings do not contain the flag.
  • For unstripped C/SDL games, start with symbol names and targeted disassembly before heavyweight game execution.
  • Render small coordinate tables as glyphs or paths early; visual encodings are common in easy game/reversing hybrids.
  • Do not normalize glyph text blindly: E-like/right-sided glyphs may be 3, and A-like glyphs may be 4 in leetspeak flags.

Dead Ends

  • The named htb texture was only a branded wall pattern, not the flag.
  • CTF LightRAG did not contain a relevant NoRadar-specific prior solve.

Tool Quirks

  • macOS otool did not parse the Linux ELF; file, strings, nm, and objdump were sufficient.
  • The harness-native RAG query validator rejected broad wording; a manually recorded missing research result was enough because local binary evidence drove the solve.

Evidence Paths

  • analysis/assets-parse-summary.txt
  • analysis/disasm-assets-green-updates.txt
  • analysis/route-table-summary.txt
  • analysis/waypoint-glyphs-ascii.txt
  • analysis/waypoint-glyphs.png
  • solve/solve.py
  • loot/flag.txt

Ingestion Decision

  • Proposed for LightRAG: yes
  • Requires user approval before ingestion: yes

Notes

Notes

Scope

  • Challenge: NoRadar
  • Category: GamePwn
  • Difficulty: Easy
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-09T11:33:10Z
  • 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/a12c736e-81ff-4edc-adda-82bb85a6024b.zip1786667<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 3 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T11:33:10Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T11:33:38Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T11:35:14Zhypothesis recordedhypothesis-board.mdStatic route extraction from green_cube3_update waypoint tableMediumParse the 189 waypoint pairs from .rodata and derive final/current green cube coordinates; validate against constructor/reset logic.
2026-06-09T11:35:14Zresearch taskanalysis/research/task-20260609T113514483249Z-681c6ef8.mdResearch task created for advisory investigationMediumRecord research output
2026-06-09T11:35:50Zresearch recordanalysis/research/research-records.mdResearch tagged MISSINGMediumValidate against current evidence
2026-06-09T11: <REDACTED>
2026-06-09T11:42:31Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval
2026-06-09T11: <REDACTED>
2026-06-09T11:48:19Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval
2026-06-09T12: <REDACTED>
2026-06-09T12:03:06Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The provided ZIP extracted to gamepwn_noradar/noradar and gamepwn_noradar/assets.dmp; see analysis/unzip.txt.
  • noradar is an unstripped Linux x86-64 SDL ELF with visible functions including green_cube3_update; see analysis/file-extracted.txt and analysis/nm.txt.
  • assets.dmp contains a 350x21 column-major map plus textures named htb, floor, and green_cube; see analysis/assets-parse-summary.txt.
  • The green_cube3_update routine copies a static waypoint table from .rodata at 0x5060; plotting zero-separated 7x7 waypoint groups renders the hidden flag glyphs; see analysis/waypoint-glyphs-ascii.txt and analysis/waypoint-glyphs.png.
  • solve/solve.py reconstructs the glyphs from the ELF. Two glyphs are leetspeak digits rather than letters: <REDACTED>, and the A-like glyph is 4. The solver writes the corrected HTB-format flag to loot/ for harness capture.

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