Challenge / Reversing

Debugme

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

MediumPublished 2025-06-21Sanitized local writeup

Scenario

Debugme attack path

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

Debugme sanitized attack graph

Walkthrough flow

01

Extracted the PE32 Windows binary from the HTB...

02

Identified anti-debug/self-modifying behavior around...

03

Decrypted virtual address range 0x401620..0x401791...

04

Inspected the recovered main, which checks PEB...

05

Simulated the arithmetic-obfuscated dword pushes in...

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.

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

  • Reversing/Debugme/writeup.md
  • htb-challenge/Reversing/Debugme/notes.md
  • htb-challenge/Reversing/Debugme/memory-summary.md
  • htb-challenge/Reversing/Debugme/hypothesis-board.md

Technical Walkthrough

Writeup

Challenge

  • Name: Debugme
  • Category: Reversing
  • Difficulty: Medium
  • Mode: file

Summary

debugme.exe hides its real main by encrypting the function bytes with XOR 0x5c.

Once decrypted statically, the function shows the intended anti-debug checks and a stack-built flag buffer.

The flag body is recovered by simulating the pushes and XORing the resulting 36 bytes with 0x4b.

Artifact Inventory

  • files/a12c7397-6d32-4799-9cac-84cc8d586fb9.zip: original HTB archive.
  • analysis/extracted/debugme.exe: PE32 Windows console binary.
  • analysis/pe-summary.txt: PE sections/imports summary.
  • analysis/main-xor5c-disasm.txt: decrypted _main disassembly used as direct solve evidence.

Analysis

Static triage showed a PE32 MinGW binary with anti-debug related imports such as QueryPerformanceCounter, GetTickCount, VirtualProtect, and exception handling APIs. Raw strings did not contain the flag, but they did contain debugger-themed bait messages.

The useful code path is self-modifying. The anti-debug stub decrypts the _main region from virtual address 0x401620 through 0x401791 by XORing each byte with 0x5c. The reproduced decrypted region is saved in analysis/main-xor5c.bin, and the disassembly is saved in analysis/main-xor5c-disasm.txt.

The decrypted code checks fs:[0x30] PEB fields and uses rdtsc timing as anti-debug checks. After those checks, it builds an encoded 36-byte buffer on the stack using arithmetic-obfuscated dword constants. The final loop sets ecx to 0x24, ebx to 0x4b, then XOR-decodes the stack buffer byte by byte.

Solve

solve/solve.py reproduces the static path:

  1. map 0x401620..0x401791 to raw PE offsets;
  2. XOR the protected region with 0x5c;
  3. save the recovered disassembly for audit;
  4. simulate the stack push order from decrypted main;
  5. XOR the encoded stack bytes with 0x4b;
  6. wrap the decoded body as an HTB flag and write it to loot/flag-candidate.txt.

The harness then captured the candidate into loot/flag.txt.

Flag

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

Lessons

  • For anti-debug reversing challenges, static decryption can be cleaner than fighting the runtime checks.
  • When x86 code builds a buffer with repeated push eax, decode from the last pushed dword first because that becomes the lowest address at esp.
  • Keep public/RAG hints advisory; the decisive evidence here was the decrypted disassembly from the current binary.

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: Debugme
  • Category: Reversing
  • Difficulty: Medium
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-15T04:28:03Z
  • 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/a12c7397-6d32-4799-9cac-84cc8d586fb9.zip27361<hash redacted>Zip archive data, at least v2.0 to extract, compression method=deflatezip entries: 1 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-15T04:28:03Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-15T04:28:35Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-15T04:28:35Zhypothesis recordedhypothesis-board.mdAnalyze the Windows binary anti-debug checks and recover the flag from guarded logic or decrypted runtime data.MediumInspect file type/imports/strings and locate anti-debug/API checks before dynamic execution.
2026-06-15T04:28:35Zcheckpoint recordedanalysis/checkpoint-triage-20260615T042835966719Z-f5b5900d.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-15T04:29:14ZRAG queryanalysis/rag/rag-query-20260615T042858674180Z-78686322.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-15T04:30:04Zinstrumentation plananalysis/instrumentation-plan.mdRecover Debugme flag from a protected PE32 Windows binary without blind execution.HighAfter two static branches fail without new facts, record failure and request debugger/Wine or Ghidra rather than guessing.
2026-06-15T04:30:04Zevaluatoranalysis/evaluator-20260615T043004561123Z-11884c67.mdProceedHighAnalyze PE imports, sections, strings, and disassembly for anti-debug and flag logic.
2026-06-15T04:30:23ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-15T04:36:22Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-15T04:36:31Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-15T04:37:30Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-15T04:37:36Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • debugme.exe is a PE32 MinGW console binary with anti-debug imports and debug sections.
  • The protected _main region at 0x401620..0x401791 is stored XOR-encrypted with key 0x5c.
  • After decrypting _main, the code checks PEB debugger flags and an rdtsc timing threshold before printing bait strings.
  • The flag body is built as 9 obfuscated pushed dwords, then decoded in-place with XOR key 0x4b over 0x24 bytes.
  • Reproducible solver: solve/solve.py.
  • Raw captured flag: 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: Reversing
  • Challenge: Debugme
  • 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. Extracted the PE32 Windows binary from the HTB archive.
  2. Identified anti-debug/self-modifying behavior around the protected _main region.
  3. Decrypted virtual address range 0x401620..0x401791 with XOR key 0x5c.
  4. Inspected the recovered main, which checks PEB debugger flags and rdtsc timing.
  5. Simulated the arithmetic-obfuscated dword pushes in stack order.
  6. XOR-decoded the 36-byte stack buffer with key 0x4b.
  7. Saved the reconstructed HTB flag through the harness capture flow.

Reusable Lessons

  • Static patch/decrypt is often faster than live debugging when the binary intentionally punishes debuggers.
  • For x86 stack-built strings, reverse the push order and preserve little-endian dword layout.
  • Record decrypted disassembly as direct-source evidence before relying on a recovered candidate.

Dead Ends

  • Raw strings did not expose the flag.
  • Generic anti-debug RAG output was useful only as a checklist, not as evidence.

Tool Quirks

  • pefile and capstone were sufficient; Wine/Ghidra/radare2 were not required.
  • The harness exploit gate required a validated research/direct-source record before capture.

Evidence Paths

  • analysis/main-xor5c-disasm.txt
  • analysis/main-xor5c.bin
  • 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
1Analyze the Windows binary anti-debug checks and recover the flag from guarded logic or decrypted runtime data.Archive contains a Windows binary; prompt says it is protected and hard to debug.Inspect file type/imports/strings and locate anti-debug/API checks before dynamic execution.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Technical analogy

How to remember this solve

Think of it like taking apart a small appliance on a workbench. You do not need every screw at once; you trace the control path and rebuild just enough logic to make it reveal the answer.

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