reversefreemedium

Debugme

HackTheBox

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.

$ ls tags/ techniques/
peb_antidebug_bypassrdtsc_timing_checkxor_self_modifying_codeentry_point_hijackingstatic_flag_extraction

Debugme — HackTheBox

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:

  1. Function _main (0x401620) contains garbage/encoded data — many 0x5c (\) bytes, int3 instructions, unreadable code
  2. _mainCRTStartup (0x4010f9) starts with jmp 0x408904 — jump to __DTOR_LIST__+0x1c section

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:

  1. PEB.BeingDebugged — checking fs:[0x30]+0x02 (debugger flag)
  2. PEB.NtGlobalFlag — checking fs:[0x30]+0x68 (debug heap flags)
  3. RDTSC timing check — two rdtsc calls, 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 _main function 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:

  1. Repeats the same anti-debug checks
  2. If debugger detected: "Looks like your doing something naughty. Stop it!!!"
  3. 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{Tr0lling_Ant1_D3buGGeR_trickz_R_fun!}

Alternative Approach: Patching Anti-Debug

You can patch the checks in a debugger:

  1. Set PEB.BeingDebugged = 0
  2. Set PEB.NtGlobalFlag = 0
  3. Skip the RDTSC check (NOP or change conditional jump)
  4. Let the code decode itself and output the flag

Key Indicators

Use this technique when:

  • Entry point contains jmp to a non-standard section (__DTOR_LIST__, .data, etc.)
  • The main function contains unreadable code or repeating bytes (XOR key)
  • There are accesses to fs:[0x30] (PEB) — sign of anti-debug
  • Paired rdtsc instructions — timing-based anti-debug
  • DWARF debug sections in Windows PE — MinGW compilation, possibly non-standard behavior
  • Strings hint at debugging: "bugs in your debugger", "find it in your debugger"

$ cat /etc/motd

Liked this one?

Pro unlocks every writeup, every flag, and API access. $9/mo.

$ cat pricing.md

$ grep --similar

Similar writeups