Indirect Memory Access
b01lersc
Task: recover a 128-input solution for a GBA ROM whose validator hides its real logic behind IWRAM helper code and DMA-driven table swaps. Solution: trace the exact executed helper path, rebuild the resulting 450-gate boolean circuit, solve the 128-bit A/not-A sequence, and decode it into the flag text.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Indirect Memory Access — b01lers CTF
Description
Original challenge statement was not preserved in the workspace.
Files provided:
chal.gba— the Game Boy Advance ROM.
The ROM prints Press Button: in a loop, emits characters from the alphabet absSRLUDrl, collects 128 inputs, and on success prints flag is 'bctf{<above chars>}'. The goal is to recover the exact accepted input sequence and decode the resulting flag contents.
Analysis
The obvious starting point is the main loop near 0x080015b4. It prompts for one button at a time, stores a per-step value in IWRAM near 0x030000a0, increments a counter at 0x0300009c, and after 0x80 iterations calls the validator at 0x08000310.
The ROM also contains the lookup string:
absSRLUDrl
At first glance the challenge looks like it may care about the full ten-button GBA input alphabet. The key reversing insight is that the validator at 0x08000310 does not preserve that full semantics. The meaningful state per position is only one bit:
Abutton →1- any non-
Abutton →0
So the real problem is not a ten-symbol input alphabet but a hidden 128-bit boolean constraint system.
The hard part is that a naïve static model is wrong. The validator at 0x08000310 relies on helper code copied into IWRAM around 0x03000025, and that helper's behavior changes depending on DMA3 state. During validation, DMA3 rewrites its source blob from several small ROM tables, so the same-looking call site can execute a different boolean gate at runtime. Static disassembly of the ROM therefore misses the exact logic that is actually checked.
To recover the real behavior, I used mGBA's GDB remote stub and traced:
...
$ grep --similar
Similar writeups
- [reverse][free]Nostalgia— hackthebox
- [reverse][Pro]Танчики (Tanks)— duckerz
- [reverse][Pro]flag_checker— kalmarctf
- [reverse][Pro]Not reverse 100% - TaipanByte CTF— taipanbyte
- [reverse][free]roulette— umdctf