title: Hack.lu 2k14 At Gunpoint - re200 author: depierre published: 2014-10-23 categories: CTF, Security, Reverse Engineering keywords: hack.lu, ctf, write-up, reverse, 200, challenge, security, radare2, gameboy, rom, bgb, hackgyver From Tuesday to Thursday, [hack.lu 2014 CTF](http://2014.hack.lu/index.php/CaptureTheFlag) was taking place. I wished I had more time to spend on the challenges. It could be nice to see this CTF over the weekend. Nevertheless the few challenges I did were fun, as expected from hack.lu. ![Gunpoint Home Screen](/static/images/hacklu/gunpoint_homescreen.png) I spent a couple of hours working on one specific challenge: At Gunpoint reverse engineering (200) and I thought I would do the write-up. # At Gunpoint - The challenge From the web page, I downloaded the challenge and ran the obvious-first command-ever-been-run *file*: :::bash depierre$ file gunpoint_2daf5fe3fb236b398ff9e5705a058a7f.dat gunpoint_2daf5fe3fb236b398ff9e5705a058a7f.dat: Gameboy ROM: "FLUX", [ROM ONLY], ROM: 256Kbit Oh... I never tried to reverse GameBoy ROM before so this could be fun :) The challenge says that I should find the secret handshake, which means the secret inputs sequence since it is a GameBoy ROM. Checking on Archlinux's AUR packages, I found [VisualBoyAdvance](https://wiki.archlinux.org/index.php/VisualBoyAdvance-M) but sadly, its debug mode wouldn't work (not F11, nor -d option). The other one I found is running on Windows and is named [bgb](http://bgb.bircd.org/). ![Gunpoint Home Screen](/static/images/hacklu/gunpoint_homescreen.png) When emulating the ROM, I have on my screen a badass pixel-art cowboy. Not knowing what do to, I try different inputs but nothing changes. ![Gunpoint Warning Screen](/static/images/hacklu/gunpoint_warningscreen.png) After 2 minutes, the cowboy gets angry and I am warned with the message above. Well, I have no idea what to do so let's ask [radare2](https://github.com/radare/radare2) :) # GameBoy and r2 I first check the entry point. According to the Internet, a GameBoy ROM will start at *0x100* as shown by r2. From there I jump to the main function (identified as such by r2) starting at ``0x150``. Sadly, I only read a lot of operations but I have no concrete idea on what they do. Showing the code wouldn't be wise since it occupies some pages. Sooooooo... What to do? It is so disturbing to see for the first time a complete new ASM. Even though some atomic operations are similar to what I am used to, such as ``xor a``, ``call 0xdead``, ``inc``, ``dec`` and so on. > It feels like programming a GameBoy ROM is 90% ``ld`` / 10% other. Sadly, r2 current GameBoy ROM support is pretty lame at detecting functions. For instance the last ``call 0x1b54`` is not recognized as a function until using the ``af`` command (not even sure that it gives the right result). :::nasm [0x00000100]> pdf @ 0x1b54 Cannot find function at 0x00001b54 [0x00000100]> af @ 0x1b54 [0x00000100]> pdf @ 0x1b54 | ; CALL XREF from 0x000001cb (fcn.00000123) | ; CALL XREF from 0x000020bd (fcn.000020af) / (fcn) fcn.00001b54 25 | 0x00001b54 e1 pop hl | 0x00001b55 faabc0 ld a, [0xc0ab] | 0x00001b58 f5 push af | 0x00001b59 5e ld e, [hl] | 0x00001b5a 23 inc hl | 0x00001b5b 56 ld d, [hl] | 0x00001b5c 23 inc hl | 0x00001b5d 2a ldi a, [hl] | 0x00001b5e 23 inc hl | 0x00001b5f e5 push hl | 0x00001b60 eaabc0 ld [0xc0ab], a | ; Bankswitch | 0x00001b63 ea0020 ld [0x2000], a | 0x00001b66 216d1b ld hl, fcn.00001b6d | 0x00001b69 e5 push hl | 0x00001b6a 6b ld l, e | 0x00001b6b 62 ld h, d \ 0x00001b6c e9 jp hl I want to say that **in this post, my use of r2 is pretty lame and not really nice**. I mostly used ``pd`` and that is all (i.e. no function renaming, variable identification and co). Why? First, I was in a hurry when reversing the ROM and second, **I wanted to keep the blog post as close as what really happened.** Anyway, the static analysis does not help me much right now. I will come back to that when I will understand how the ROM works. # ROM Profiler What do I have so far? Not much to be honest. When the ROM boots, a cowboy appears. After 2 minutes without the right inputs, a warning message is shown. That is all I know. But even *that* is something. The ROM will wait for inputs until the correct sequence is found. That means that there should be some kind of interrupts and interrupt handler, where the interrupts are generated by the JOYPAD and the handler would be some ``check_flag``-like function (or at least drive me close to that function). According to the [GameBoy CPU Manual](http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf), the ``halt`` instruction I see at the end of the main: :::nasm | ; JMP XREF from 0x000001d3 (fcn.00000123) | 0x000001d2 76 halt \ 0x000001d3 18fd jr 0xfd ; (main) Will halt the program until an interrupt is raised. So what I am looking for is some kind of a callback function that will retrieve the JOYPAD pressed button. # Interrupt handler Thanks to r2, this is easy because I will only check where the JOYPAD is referenced and disassemble there. ::: [0x00000100]> CC*~JOYPAD "CCu JOYPAD" @ 0x00001e63 "CCu JOYPAD" @ 0x00001e65 "CCu JOYPAD" @ 0x00001e67 "CCu JOYPAD" @ 0x00001e71 "CCu JOYPAD" @ 0x00001e73 "CCu JOYPAD" @ 0x00001e75 "CCu JOYPAD" @ 0x00001e77 "CCu JOYPAD" @ 0x00001e79 "CCu JOYPAD" @ 0x00001e7b "CCu JOYPAD" @ 0x00001e7d "CCu JOYPAD" @ 0x00001e88 Looking for a function around the first *JOYPAD* reference, r2 finds: :::nasm hl_lines="6" [0x00000100]> pdf @ 0x00001e63 | ; CALL XREF from 0x00001e54 (fcn.00001e50) | ; CALL XREF from 0x00001e8d (fcn.00001e8d) | ; CALL XREF from 0x00001e94 (fcn.00001e94) / (fcn) fcn.00001e60 45 | 0x00001e60 c5 push bc | 0x00001e61 3e20 ld a, 0x20 | 0x00001e63 e000 ld [0xff00], a ; JOYPAD | 0x00001e65 f000 ld a, [0xff00] ; JOYPAD | 0x00001e67 f000 ld a, [0xff00] ; JOYPAD | 0x00001e69 2f cpl | 0x00001e6a e60f and 0x0f | 0x00001e6c cb37 swap a | 0x00001e6e 47 ld b, a | 0x00001e6f 3e10 ld a, 0x10 | 0x00001e71 e000 ld [0xff00], a ; JOYPAD | 0x00001e73 f000 ld a, [0xff00] ; JOYPAD | 0x00001e75 f000 ld a, [0xff00] ; JOYPAD | 0x00001e77 f000 ld a, [0xff00] ; JOYPAD | 0x00001e79 f000 ld a, [0xff00] ; JOYPAD | 0x00001e7b f000 ld a, [0xff00] ; JOYPAD | 0x00001e7d f000 ld a, [0xff00] ; JOYPAD | 0x00001e7f 2f cpl | 0x00001e80 e60f and 0x0f | 0x00001e82 b0 or b | 0x00001e83 cb37 swap a | 0x00001e85 47 ld b, a | 0x00001e86 3e30 ld a, 0x30 | 0x00001e88 e000 ld [0xff00], a ; JOYPAD | 0x00001e8a 78 ld a, b | 0x00001e8b c1 pop bc \ 0x00001e8c c9 ret I feel lucky but this snippet looks a lot alike the one from the CPU Manual, the one about the interrupts (page 36). Setting a breakpoint on ``0x00001e60`` in *bgb* helps me to understand how this works. Depending on what JOYPAD button I press, the ``a`` register will vary. For instance when pressing ``A``: ![BGB Joypad](/static/images/hacklu/bgb_joypad.png) ![BGB Before Handler](/static/images/hacklu/bgb_handler_before.png) ![BGB After Handler](/static/images/hacklu/bgb_handler_after.png) *(Notice the ``a = 0x10``)* When pressing ``B``: ![BGB Joypad 2](/static/images/hacklu/bgb_joypad2.png) ![BGB Before Handler 2](/static/images/hacklu/bgb_handler_before2.png) ![BGB After Handler 2](/static/images/hacklu/bgb_handler_after2.png) *(Notice the ``a = 0x20``)* +-------------+--------------+ | $80 - Start | $40 - Select | +-------------+--------------+ | $4 - Up | $8 - Down | +-------------+--------------+ | $2 - Left | $1 - Right | +-------------+--------------+ | $20 - B | $10 - A | +-------------+--------------+ From the manual (page 37), ``A == 0x10`` and ``B == 0x20``. That means I found the interrupt hanlder, sweet :) # To interrupt handler, and beyond Now that I have located the handler that retrieves the pressed button from the interruption, I simply follow the execution flow with *bgb*. :::nasm 0x00001e60() ; main 0x00001e97 5f ld e, a 0x00001e98 c9 ret After retrieving the current pressed button into ``a``, the ROM will save ``a`` into the ``e`` register: Then it continues on ``0xd72``. # Meaning of the variables :::nasm 0x00000d72 21a2c0 ld hl, 0xc0a2 0x00000d75 73 ld [hl], e 0x00000d76 21a1c0 ld hl, 0xc0a1 0x00000d79 7e ld a, [hl] 0x00000d7a 21a2c0 ld hl, 0xc0a2 0x00000d7d be cp [hl] 0x00000d7e 2003 jr nZ, 0x03 0x00000d80 c3f60e jp 0x0ef6 I do not know what is stored at ``0xc0a2`` nor ``0xc0a1`` but I will use *bgb* and set a write access breakpoint on these offsets. ![BGB Access Breakpoint](/static/images/hacklu/bgb_access_breakpoints.png) When resuming, *bgb* stops here: :::nasm 0x00000ef1 21a0c0 ld hl, 0xc0a0 0x00000ef4 3600 ld [hl], 0x00 ; 0xc0ac <- 0 0x00000ef6 21a2c0 ld hl, 0xc0a2 0x00000ef9 7e ld a, [hl] ; a <- 0xc0a2 0x00000efa 21a1c0 ld hl, 0xc0a1 0x00000efd 77 ld [hl], a ; 0xc0a1 <- a 0x00000efe c36f0d jp 0x0d6f 0x00000f01 c9 ret From the values stored in ``0xc0a2`` that I monitored using the emulator, it corresponds to the current pressed button. Therefore, the previous snippet: + ``0xc0a2 <- e`` (remember that ``e`` is the current input) + ``a <- 0xc0a1`` (retrieve the previous input) + ``a != e?`` (if they are equals, it jumps further and exit) That means the rest of the function only runs when the user presses a button different from the previous one (a way to trigger the rest when the first input is met). :::nasm 0x00000d7d be cp [hl] 0x00000d7e 2003 jr nZ, 0x03 ; . . . 0x00000d83 21a0c0 ld hl, 0xc0a0 0x00000d86 7e ld a, [hl] 0x00000d87 fe0d cp 0x0d 0x00000d89 c2990d jp nZ, 0x0d99 Here I can see once again ``0xc0a0`` which is compared to ``0x0d`` (13). It really looks like a counter (let's say ``i``) and that the secret handshake is composed of 13 different inputs (0 to 12). So far: + ``0xc0a0`` is the index of the current input + ``0xc0a1`` is the previous user input + ``0xc0a2`` is the current user input # The algorithm :::nasm 0x00000d87 fe0d cp 0x0d 0x00000d89 c2990d jp nZ, 0x0d99 ; . . . 0x00000d99 21a2c0 ld hl, 0xc0a2 0x00000d9c 7e ld a, [hl] ; get current input 0x00000d9d e604 and 0x04 ; is it UP? 0x00000d9f 2003 jr nZ, 0x03 ; YES 0x00000da1 c3c90d jp 0x0dc9 0x00000da4 21a0c0 ld hl, 0xc0a0 0x00000da7 7e ld a, [hl] ; retrieve i 0x00000da8 b7 or a ; is i == 0 ? 0x00000da9 caba0d jp Z, 0x0dba ; YES 0x00000dac 21a0c0 ld hl, 0xc0a0 0x00000daf 7e ld a, [hl] ; retrieve i 0x00000db0 fe04 cp 0x04 ; is i == 4? 0x00000db2 c2c10d jp nZ, 0x0dc1 ; NO then goto RESET i 0x00000db5 1803 jr 0x03 0x00000db7 c3c10d jp 0x0dc1 0x00000dba 21a0c0 ld hl, 0xc0a0 0x00000dbd 34 inc [hl] ; i += 1 0x00000dbe c38a0e jp 0x0e8a ; goto end 0x00000dc1 21a0c0 ld hl, 0xc0a0 0x00000dc4 3600 ld [hl], 0x00 ; RESET i 0x00000dc6 c38a0e jp 0x0e8a ; goto end First it checks if the current input corresponds to *UP*. If so, is it the first or the fifth input? If they are then ``0xc0a0`` is incremented. The rest of that function is very similar. It checks which button is currently pressed (one after the other) and what is the current value of ``i`` (to check if it is the correct sequence). In other words, it looks like: :::python if input == UP: if sequence_index == 0 or sequence_index == 4: sequence_index += 1 else sequence_index = 0 elif input == RIGHT: if sequence_index == 1 or sequence_index == 5: sequence_index += 1 else sequence_index = 0 # . . . Using a piece of paper and a pencil, I find the following inputs: > Up Right Down Left Up Right Down Left B B A A Start ![Gunpoint Flag Screen](/static/images/hacklu/gunpoint_flagscreen.png) Hence the flag, sweet sweet flag: > tkCXDJheQDNRN **\o/**