N
Back to writeup archive
Hack@10 International Capture The Flag Pre-Eliminary Round 2026

detonator

Executable triage with strings, object analysis, and scripted flag recovery.

Reverse EngineeringMarkdown + PDFMediumsolved2 minread·467words
route
/TryN3rr0r/writeups/hack10-pre-eliminary-2026/detonator
archive index
6 / 15
read mode
parsed markdown
Writeup loaded.

detonator

challenge brief
target profile, scoring, and execution stack
verified solve
target
detonator.exe
category
Reverse Engineering
points
500
difficulty
Medium
flag format
HACK10{}
tools used
lsfilestringsxxdobjdumppython3
final flag
HACK10{be029cf0e9f2eaa5f80489343630befb}
reveal and copy from section 5

1. Challenge Overview

detonator.exe is a 64-bit Windows console PE binary. The challenge description hints at malware-style detonation and sandboxing, but the note explicitly says no brute forcing or scanning is required. The objective is to reverse the binary statically, identify the true flag generation logic, and recover the final flag in the format HACK10{...}.

PDF evidence frame 01

2. Initial Reconnaissance

I started with basic triage to identify the file type, inspect obvious strings, and dump the binary header.

Command:

bash1 lines
1ls -la

Output:

bash6 lines
1total 3242drwxr-xr-x  4 nopalinto nopalinto  28672 Mar 27 10:03 .3drwxr-xr-x 14 nopalinto nopalinto   4096 Mar 27 10:03 ..4drwxrwxr-x  2 nopalinto nopalinto   4096 Feb  7 09:49 .codex5drwxrwxr-x  5 nopalinto nopalinto   4096 Feb 13 06:44 .venv6-rw-rw-r--  1 nopalinto nopalinto 284430 Mar 27 10:03 detonator.exe

Command:

bash1 lines
1file detonator.exe

Output:

bash1 lines
1detonator.exe: PE32+ executable for MS Windows 5.02 (console), x86-64, 19 sections

Command:

bash1 lines
1strings -a -n 6 detonator.exe | sed -n '1,220p'

Output:

bash201 lines
1!This program cannot be run in DOS mode.2`.data3.rdata4@.pdata5@.xdata6.idata7@.reloc8AWAVAUATUWVSH9X[^_]A\\A]A^A_108MZuEHcP<H11UAWAVAUATWVSH12[^_A\\A]A^A_]13([^_]H14@' t	H15@$A9@(\~16AWAVAUATUWVSH17C$9C(\~18H[^_]A\\A]A^A_19S$9S(\~20S$9S(\~21UAWAVAUATWVSH22C$9C(\~23C$9C(\~24[^_A\\A]A^A_]25UAWAVAUATWVSH26C$9C(\~27C$9C(\~28[^_A\\A]A^A_]29UAVWVSH30C$9C(\~31[^_A^]32[^_A^]33=UUUUw34S$9S(\~35AUATUWVSH36X[^_]A\\A]37AWAVAUATUWVSH38[^_]A\\A]A^A_39AWAVAUATUWVSH408[^_]A\\A]A^A_41AWAVAUATUWVSH42[^_]A\\A]A^A_43[^_]A\\A]A^A_44D$L)D$`45T$8HcD$L;B46D$`+D$H47ATUWVSLcY48[^_]A\\49[^_]A\\50AWAVAUATUWVSH518[^_]A\\A]A^A_52AVAUATUWVSH53 [^_]A\\A]A^54AUATUWVSH55([^_]A\\A]56([^_]A\\A]57WVSHcA58H9E0sRH59%02x%02x%02x%02x60C:\\Users\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\Desktop\\local.txt61HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}62File not found. Keep looking...63Here is the flag: HACK10{64__pos <= size()65std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator[](size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; reference = char\&; size_type = long long unsigned int]66C:/msys64/ucrt64/include/c++/15.2.0/bits/basic_string.h67basic_string: construction from null is not valid68basic_string::_M_create69Argument domain error (DOMAIN)70Argument singularity (SIGN)71Overflow range error (OVERFLOW)72Partial loss of significance (PLOSS)73Total loss of significance (TLOSS)74The result is too small to be represented (UNDERFLOW)75Unknown error76_matherr(): %s in %s(%g, %g)  (retval=%g)77Mingw-w64 runtime failure:78Address %p has no image-section79  VirtualQuery failed for %d bytes at address %p80  VirtualProtect failed with code 0x%x81  Unknown pseudo relocation protocol version %d.82  Unknown pseudo relocation bit size %d.83%d bit pseudo relocation at %p out of range, targeting %p, yielding the value %p.84(null)85Infinity86runtime error %d87GCC: (Rev8, Built by MSYS2 project) 15.2.088GCC: (Rev8, Built by MSYS2 project) 15.2.089GCC: (Rev8, Built by MSYS2 project) 15.2.090GCC: (Rev8, Built by MSYS2 project) 15.2.091GCC: (Rev8, Built by MSYS2 project) 15.2.092GCC: (Rev8, Built by MSYS2 project) 15.2.093GCC: (Rev8, Built by MSYS2 project) 15.2.094GCC: (Rev8, Built by MSYS2 project) 15.2.095GCC: (Rev8, Built by MSYS2 project) 15.2.096GCC: (Rev8, Built by MSYS2 project) 15.2.097GCC: (Rev8, Built by MSYS2 project) 15.2.098GCC: (Rev8, Built by MSYS2 project) 15.2.099GCC: (Rev8, Built by MSYS2 project) 15.2.0100GCC: (Rev8, Built by MSYS2 project) 15.2.0101GCC: (Rev8, Built by MSYS2 project) 15.2.0102GCC: (Rev8, Built by MSYS2 project) 15.2.0103GCC: (Rev8, Built by MSYS2 project) 15.2.0104GCC: (Rev8, Built by MSYS2 project) 15.2.0105GCC: (Rev8, Built by MSYS2 project) 15.2.0106GCC: (Rev8, Built by MSYS2 project) 15.2.0107GCC: (Rev8, Built by MSYS2 project) 15.2.0108GCC: (Rev8, Built by MSYS2 project) 15.2.0109GCC: (Rev8, Built by MSYS2 project) 15.2.0110GCC: (Rev8, Built by MSYS2 project) 15.2.0111GCC: (Rev8, Built by MSYS2 project) 15.2.0112GCC: (Rev8, Built by MSYS2 project) 15.2.0113GCC: (Rev8, Built by MSYS2 project) 15.2.0114GCC: (Rev8, Built by MSYS2 project) 15.2.0115GCC: (Rev8, Built by MSYS2 project) 15.2.0116GCC: (Rev8, Built by MSYS2 project) 15.2.0117GCC: (Rev8, Built by MSYS2 project) 15.2.0118GCC: (Rev8, Built by MSYS2 project) 15.2.0119GCC: (Rev8, Built by MSYS2 project) 15.2.0120GCC: (Rev8, Built by MSYS2 project) 15.2.0121GCC: (Rev8, Built by MSYS2 project) 15.2.0122GCC: (Rev8, Built by MSYS2 project) 15.2.0123GCC: (Rev8, Built by MSYS2 project) 15.2.0124GCC: (Rev8, Built by MSYS2 project) 15.2.0125GCC: (Rev8, Built by MSYS2 project) 15.2.0126GCC: (Rev8, Built by MSYS2 project) 15.2.0127_Unwind_Resume128DeleteCriticalSection129EnterCriticalSection130GetLastError131InitializeCriticalSection132LeaveCriticalSection133SetUnhandledExceptionFilter134TlsGetValue135VirtualProtect136VirtualQuery137mbrtowc138wcrtomb139__p__environ140_stat64i32141_set_new_mode142calloc143malloc144_configthreadlocale145localeconv146__setusermatherr147__C_specific_handler148memcpy149__p___argc150__p___argv151_cexit152_configure_narrow_argv153_crt_atexit154_errno155_initialize_narrow_environment156_set_app_type157_initterm158_initterm_e159_set_invalid_parameter_handler160signal161strerror162__acrt_iob_func163__p__commode164__p__fmode165__stdio_common_vfprintf166strlen167strncmp168strnlen169wcslen170wcsnlen171_ZSt17__throw_bad_allocv172_ZSt19__throw_logic_errorPKc173_ZSt20__throw_length_errorPKc174_ZSt21__glibcxx_assert_failPKciS0_S0_175_ZSt4cout176_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc177_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE178_ZdlPvy179__gxx_personality_seh0180libgcc_s_seh-1.dll181KERNEL32.dll182api-ms-win-crt-convert-l1-1-0.dll183api-ms-win-crt-environment-l1-1-0.dll184api-ms-win-crt-filesystem-l1-1-0.dll185api-ms-win-crt-heap-l1-1-0.dll186api-ms-win-crt-locale-l1-1-0.dll187api-ms-win-crt-math-l1-1-0.dll188api-ms-win-crt-private-l1-1-0.dll189api-ms-win-crt-runtime-l1-1-0.dll190api-ms-win-crt-stdio-l1-1-0.dll191api-ms-win-crt-string-l1-1-0.dll192libstdc++-6.dll193<?xml version="1.0" encoding="UTF-8" standalone="yes"?>194<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">195  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">196    <security>197      <requestedPrivileges>198        <requestedExecutionLevel level="asInvoker"/>199      </requestedPrivileges>200    </security>201  </trustInfo>

Command:

bash1 lines
1xxd -l 512 detonator.exe

Output:

bash32 lines
100000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000  MZ..............200000010: b800 0000 0000 0000 4000 0000 0000 0000  ........@.......300000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................400000030: 0000 0000 0000 0000 8000 0000 0000 0000  ................500000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468  ........!..L.!Th600000050: 6973 2070 726f 6772 616d 2063 616e 6e6f  is program canno700000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS 800000070: 6d6f 6465 2e0d 0d0a 2400 0000 0000 0000  mode....$.......900000080: 5045 0000 6486 1300 451e c569 004a 0300  PE..d...E..i.J..1000000090: 5f0a 0000 f000 2600 0b02 022d 008a 0000  _.....\&....-....11000000a0: 0040 0000 000c 0000 0014 0000 0010 0000  .@..............12000000b0: 0000 0040 0100 0000 0010 0000 0002 0000  ...@............13000000c0: 0400 0000 0000 0000 0500 0200 0000 0000  ................14000000d0: 0000 0400 0006 0000 493d 0500 0300 6001  ........I=....`.15000000e0: 0000 2000 0000 0000 0010 0000 0000 0000  .. .............16000000f0: 0000 1000 0000 0000 0010 0000 0000 0000  ................1700000100: 0000 0000 1000 0000 0000 0000 0000 0000  ................1800000110: 0000 0100 a40c 0000 0020 0100 e804 0000  ......... ......1900000120: 00d0 0000 1806 0000 0000 0000 0000 0000  ................2000000130: 0030 0100 7000 0000 0000 0000 0000 0000  .0..p...........2100000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................2200000150: c0b4 0000 2800 0000 0000 0000 0000 0000  ....(...........2300000160: 0000 0000 0000 0000 6003 0100 4802 0000  ........`...H...2400000170: 0000 0000 0000 0000 0000 0000 0000 0000  ................2500000180: 0000 0000 0000 0000 2e74 6578 7400 0000  .........text...2600000190: 9088 0000 0010 0000 008a 0000 0006 0000  ................27000001a0: 0000 0000 0000 0000 0000 0000 2000 0060  ............ ..`28000001b0: 2e64 6174 6100 0000 d000 0000 00a0 0000  .data...........29000001c0: 0002 0000 0090 0000 0000 0000 0000 0000  ................30000001d0: 0000 0000 4000 00c0 2e72 6461 7461 0000  ....@....rdata..31000001e0: 6015 0000 00b0 0000 0016 0000 0092 0000  `...............32000001f0: 0000 0000 0000 0000 0000 0000 4000 0040  ............@..@
PDF evidence frame 02

3. Analysis / Forensics Path

The first important clue in the string dump was that the binary contains both a fake flag and a Windows path that embeds that fake flag:

text4 lines
1C:\\Users\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\Desktop\\local.txt2HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}3File not found. Keep looking...4Here is the flag: HACK10{

At this point the working hypothesis was that the fake flag is used as bait inside a filesystem path and the real flag is derived from that full path.

To confirm that, I inspected the PE symbol table and disassembled the named flag-checking function.

Command:

bash1 lines
1objdump -t detonator.exe | grep -E ' main$|WinMain|flag|local|read|print|sub_' | sed -n '1,220p'

Output:

bash4 lines
1[ 35](sec  3)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000c10 .rdata$.refptr.__globallocalestatus2[ 49](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 1) 0x00000000000003e0 WinMainCRTStartup3[129](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 1) 0x00000000000009cf _Z10check_flagv4[133](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 1) 0x0000000000000b7e main

Command:

bash1 lines
1objdump -d -Mintel --disassemble=_Z10check_flagv detonator.exe

Output:

bash15 lines
100000001400019cf <_Z10check_flagv>:2   1400019ee:	48 8d 15 23 98 00 00 	lea    rdx,[rip+0x9823]        # 14000b218 <_ZL1S+0x118>3   1400019ff:	e8 7c 7c 00 00       	call   140009680 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1IS3_EEPKcRKS3_>4   140001a1f:	48 8d 15 42 98 00 00 	lea    rdx,[rip+0x9842]        # 14000b268 <_ZL1S+0x168>5   140001a30:	e8 4b 7c 00 00       	call   140009680 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1IS3_EEPKcRKS3_>6   140001a5b:	e8 d0 6e 00 00       	call   140008930 <stat64i32>7   140001a60:	85 c0                	test   eax,eax8   140001a67:	74 1d                	je     140001a86 <_Z10check_flagv+0xb7>9   140001a69:	48 8d 15 30 98 00 00 	lea    rdx,[rip+0x9830]        # 14000b2a0 <_ZL1S+0x1a0>10   140001a7a:	e8 41 01 00 00       	call   140001bc0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>11   140001a86:	48 8d 15 34 98 00 00 	lea    rdx,[rip+0x9834]        # 14000b2c1 <_ZL1S+0x1c1>12   140001a97:	e8 24 01 00 00       	call   140001bc0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>13   140001aaa:	e8 a1 f9 ff ff       	call   140001450 <_ZL3md5RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE>14   140001ab9:	e8 fa 00 00 00       	call   140001bb8 <_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE>15   140001ac1:	48 8d 05 13 98 00 00 	lea    rax,[rip+0x9813]        # 14000b2db <_ZL1S+0x1db>

This shows the exact logic:

Build a std::string from the hardcoded path at .rdata+0x218.

Check whether the path exists with _stat64i32.

If it exists, print Here is the flag: HACK10{.

Call the internal MD5 function on that path string.

Print the MD5 digest and append }.

The .rdata dump confirms the relevant literals:

text12 lines
114000b210 00000000 00000000 433a5c55 73657273  ........C:\\Users214000b220 5c484143 4b31307b 66346b33 5f666c34  \\HACK10{f4k3_fl4314000b230 675f6275 375f7930 755f3472 335f696e  g_bu7_y0u_4r3_in414000b240 5f376833 5f726967 68375f37 7234636b  _7h3_righ7_7r4ck514000b250 7d5c4465 736b746f 705c6c6f 63616c2e  }\\Desktop\\local.614000b260 74787400 00000000 4841434b 31307b66  txt.....HACK10{f714000b270 346b335f 666c3467 5f627537 5f793075  4k3_fl4g_bu7_y0u814000b280 5f347233 5f696e5f 3768335f 72696768  _4r3_in_7h3_righ914000b290 375f3772 34636b7d 00000000 00000000  7_7r4ck}........1014000b2a0 46696c65 206e6f74 20666f75 6e642e20  File not found.1114000b2c0 00486572 65206973 20746865 20666c61  .Here is the fla1214000b2d0 673a2048 41434b31 307b007d 0a005f5f  g: HACK10{.}..__
PDF evidence frame 03

4. Exploitation / Recovery

Since the binary computes MD5("C:\\\\Users\\\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\\\Desktop\\\\local.txt"), the recovery path is simply to reproduce that digest locally.

Exact solver script used:

python8 lines
1#!/usr/bin/env python32import hashlib3def main() -> None:4    path = r"C:\\Users\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\Desktop\\local.txt"5    digest = hashlib.md5(path.encode()).hexdigest()6    print(f"HACK10{{{digest}}}")7if __name__ == "__main__":8    main()

Exact command used to execute the solver:

bash1 lines
1python3 solve_detonator.py

Output:

captured flag
HACK10{be029cf0e9f2eaa5f80489343630befb}

I also verified the digest directly against the byte string recovered from the binary:

Command:

bash10 lines
1python3 - <<'PY'2from pathlib import Path3b = Path('detonator.exe').read_bytes()4needle = b'C:\\\\Users\\\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\\\Desktop\\\\local.txt\\x00'5off = b.find(needle)6print('offset:', hex(off))7print('slice :', b[off:off+len(needle)])8import hashlib9print('md5   :', hashlib.md5(needle[:-1]).hexdigest())10PY

Output:

bash3 lines
1offset: 0x94182slice : b'C:\\\\Users\\\\HACK10{f4k3_fl4g_bu7_y0u_4r3_in_7h3_righ7_7r4ck}\\\\Desktop\\\\local.txt\\x00'3md5   : be029cf0e9f2eaa5f80489343630befb

5. Flag

captured flag
HACK10{be029cf0e9f2eaa5f80489343630befb}

6. Summary of Approach & Key Takeaways

Triaged the sample as a 64-bit Windows PE compiled with MinGW.

Used strings to identify a fake embedded flag, a suspicious Windows path, and a partial flag-printing string.

Used the preserved symbol table to find _Z10check_flagv and disassembled it.

Confirmed that the program checks for the existence of the hardcoded path and, on success, prints HACK10{ plus the MD5 of that exact path string.

Reproduced the MD5 digest in Python and recovered the final flag.

Fake flags embedded in strings are often bait, not the real answer.

When symbols are present, go straight to named functions before doing deeper blind reversing.

A malware-themed description can still resolve to a simple static derivation path.

Rebuilding the program logic outside the binary is often faster and cleaner than emulating execution.