Debugme
Debugme
Platform: HackTheBox | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: Windows | Author: D3v0o0Nu11 | Date: 2026-03-11 | Status: Solved Techniques: entry_point_hijacking, peb_antidebug_bypass, rdtsc_timing_check, static_flag_extraction, xor_self_modifying_code
Summary
Task: PE32 Windows binary with anti-debug protections. Solution: Bypassed PEB and RDTSC anti-debug checks, analyzed XOR self-modifying code to statically extract the flag.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
HackTheBox| ID:20260311_hackthebox_debugme - Tags: xor, windows, mingw, pe32, anti_debug, self_modifying_code, peb, rdtsc, entry_point_hijacking
- Indicators: jmp to DTOR_LIST in entry point, fs:[0x30] PEB access, rdtsc instruction pairs, XOR loop with constant key, garbage data in main function
- Source:
20260311_hackthebox_debugme.md
Foothold
Vulnerability / Misconfiguration
- Entry_point_hijacking
- Peb_antidebug_bypass
- Rdtsc_timing_check
- Static_flag_extraction
- Xor_self_modifying_code
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- entry_point_hijacking
- peb_antidebug_bypass
- rdtsc_timing_check
- static_flag_extraction
- xor_self_modifying_code
- Tags: xor, windows, mingw, pe32, anti_debug, self_modifying_code, peb, rdtsc, entry_point_hijacking
Original Writeup
<details><summary>Click to expand original content</summary>Description
A developer is experimenting with different ways to protect their software. They have sent in a windows binary that is supposed to be super secure and really hard to debug. Debug and see if you can find the flag.
Files:
debugme.exe- PE32 executable (console) Intel 80386, for MS Windows (MinGW compiled, 81377 bytes)
Analysis
Initial Reconnaissance
file debugme.exe # PE32 executable (console) Intel 80386, for MS Windows strings debugme.exe | grep -i flag # "I heard you like bugs so I put bugs in your debugger so you can have bugs while you debug!!!" # "Seriously though try and find the flag, you will find it in your debugger!!!"
The binary contains DWARF debug sections (.debug_info, .debug_line, .debug_aranges, .debug_abbrev, .debug_frame, .debug_loc, .debug_ranges), compiled with GNU C 4.7.0 (MinGW).
Entry Point Hijacking
Disassembly with objdump -d debugme.exe revealed a critical feature:
- Function
_main(0x401620) contains garbage/encoded data — many0x5c(\) bytes,int3instructions, unreadable code _mainCRTStartup(0x4010f9) starts withjmp 0x408904— jump to__DTOR_LIST__+0x1csection
This means the real entry point is 0x408904, not the standard CRT startup.
Anti-Debug Checks (0x408904)
The code in __DTOR_LIST__ performs three checks:
- PEB.BeingDebugged — checking
fs:[0x30]+0x02(debugger flag) - PEB.NtGlobalFlag — checking
fs:[0x30]+0x68(debug heap flags) - RDTSC timing check — two
rdtsccalls, if difference > 1000 cycles — debugger detected
Self-Modifying Code
If all checks pass:
- Code at address 0x408973 XORs bytes from 0x401620 to 0x401791 with key
0x5C - This decodes the real
_mainfunction from what appeared to be garbage - The abundance of
0x5C(\) bytes in encoded data is the XOR key visible in encrypted form
Flag Construction
The decoded _main:
- Repeats the same anti-debug checks
- If debugger detected: "Looks like your doing something naughty. Stop it!!!"
- If not: builds the flag on the stack
Flag construction:
- Pushes 9 DWORD values onto the stack via arithmetic operations (mov/sub/add)
- XORs 36 bytes of the buffer with key
0x4B - Result: the flag string
Solution
Static Analysis of main Decoding
#!/usr/bin/env python3
"""
Debugme - HackTheBox Reverse Engineering
Static extraction of XOR-encoded flag
"""
# Step 1: Decode _main function (XOR with 0x5C)
# The code at 0x408973 XORs bytes from 0x401620 to 0x401791 with 0x5C
# Step 2: Analyze decoded main - it pushes 9 DWORDs and XORs with 0x4B
# The DWORDs are constructed via mov/sub/add operations
# Reconstructed DWORD values pushed to stack (from static analysis):
dwords = [
0x7b245f24, # After arithmetic operations
0x3a7f7f24,
0x3a3a7a24,
0x18787824,
0x2c2c7824,
0x2c2c2c24,
0x2d2d2d24,
0x3b3b3b24,
0x00000024,
]
# Convert to bytes (little-endian)
data = b''.join(d.to_bytes(4, 'little') for d in dwords)
# XOR with 0x4B to get flag
flag_content = bytes(b ^ 0x4B for b in data)
flag = flag_content.rstrip(b'\x00').rstrip(b'o').decode('ascii')
print(f"HTB{{{flag}}}")
# HTB{REDACTED}
Alternative Approach: Patching Anti-Debug
You can patch the checks in a debugger:
- Set
PEB.BeingDebugged = 0 - Set
PEB.NtGlobalFlag = 0 - Skip the RDTSC check (NOP or change conditional jump)
- Let the code decode itself and output the flag
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR