Flare-On 4: Challenge 9 Quick Solution

This is an Arduino (AVR) challenge. You can read the full official solution from FireEye, here I just want to show how we can just find use “grep” to quickly find the decryption function to get the flag.

At first, I was going to try to understand what this binary does, but before going too deep, I had an idea: this binary is so small, what if I can just find the flag string without looking at the program’s logic. Looking at the strings present in the binary, it is obvious The flag is not in cleartext, so it must be encrypted somehow.

Most encryption algorithm will involve the use of XOR (eor in AVR). Looking at the disassembly, all EORs are just to clear a register (e.g: eor r1, r1). There is only one eor in 0xaee that is not clearing a register (eor r25, r24), which is the last one in this grep output.

<br />
$ avr-objdump -m avr -D remorse.ino.hex |grep eor<br />
      c4:	11 24       	eor	r1, r1<br />
     1ec:	99 27       	eor	r25, r25<br />
     2e6:	99 27       	eor	r25, r25<br />
     340:	11 27       	eor	r17, r17<br />
     59e:	88 27       	eor	r24, r24<br />
     742:	11 24       	eor	r1, r1<br />
     78e:	11 24       	eor	r1, r1<br />
     7f2:	11 24       	eor	r1, r1<br />
     904:	11 24       	eor	r1, r1<br />
     a16:	11 24       	eor	r1, r1<br />
     aee:	98 27       	eor	r25, r24<br />

Looking at the code around it: it is a single loop, with eor and subi. This must be the decrypt loop.

<br />
  ae6:       ldi     r26, 0x6C       ; 108<br />
  ae8:       ldi     r27, 0x05       ; 5<br />
  aea:       ldi     r18, 0x00       ; 0</p>
<p>decrypt:<br />
  aec:       ld      r25, Z+<br />
  aee:       eor     r25, r24<br />
  af0:       add     r25, r18<br />
  af2:       st      X+, r25<br />
  af4:       subi    r18, 0xFF       ; 255<br />
  af6:       cpi     r18, 0x17       ; 23<br />
  af8:       brne    .-14            ; 0xaec<br />

We just need to find the encrypted data pointed by Z (which is a pair of R31:R30), and r24 (the xor key). Looking a bit up, we found the code that fills in the encrypted data. It sets Z with the value of Y (pair of R29:R28), clears the memory, and fill it with some bytes.

<br />
  a80:   movw    r30, r28        ; Z = Y<br />
  a82:   adiw    r30, 0x01       ; Z++<br />
  a84:   movw    r26, r30        ; X = Z<br />
  a86:   ldi     r25, 0xFF       ;<br />
  a88:   add     r25, r30        ; </p>
<p>clear:<br />
  a8a:   st      X+, r1<br />
  a8c:   cpse    r25, r26<br />
  a8e:   rjmp    .-6             ; 0xa8a </p>
<p>  a90:   ldi     r25, 0xB5<br />
  a92:   std     Y+1, r25<br />
  a94:   std     Y+2, r25<br />
  a96:   ldi     r25, 0x86<br />
  a98:   std     Y+3, r25<br />
  a9a:   ldi     r25, 0xB4<br />
  a9c:   std     Y+4, r25<br />
  a9e:   ldi     r25, 0xF4<br />
  aa0:   std     Y+5, r25<br />
  aa2:   ldi     r25, 0xB3<br />
  aa4:   std     Y+6, r25<br />
  aa6:   ldi     r25, 0xF1<br />
  aa8:   std     Y+7, r25<br />
  aaa:   ldi     r18, 0xB0<br />
  aac:   std     Y+8, r18<br />
  aae:   std     Y+9, r18<br />
  ab0:   std     Y+10, r25<br />
  ab2:   ldi     r25, 0xED<br />
  ab4:   std     Y+11, r25<br />
  ab6:   ldi     r25, 0x80<br />
  ab8:   std     Y+12, r25<br />
  aba:   ldi     r25, 0xBB<br />
  abc:   std     Y+13, r25<br />
  abe:   ldi     r25, 0x8F<br />
  ac0:   std     Y+14, r25<br />
  ac2:   ldi     r25, 0xBF<br />
  ac4:   std     Y+15, r25<br />
  ac6:   ldi     r25, 0x8D<br />
  ac8:   std     Y+16, r25<br />
  aca:   ldi     r25, 0xC6<br />
  acc:   std     Y+17, r25<br />
  ace:   ldi     r25, 0x85<br />
  ad0:   std     Y+18, r25<br />
  ad2:   ldi     r25, 0x87<br />
  ad4:   std     Y+19, r25<br />
  ad6:   ldi     r25, 0xC0<br />
  ad8:   std     Y+20, r25<br />
  ada:   ldi     r25, 0x94<br />
  adc:   std     Y+21, r25<br />
  ade:   ldi     r25, 0x81<br />
  ae0:   std     Y+22, r25<br />
  ae2:   ldi     r25, 0x8C<br />
  ae4:   std     Y+23, r25<br />

Going a bit up again, we found a ret (return), which means its the end of another function/subroutine. It seems that r24 is filled somewhere else by the caller of this decrypt function.

It doesn’t matter, r24 is just an 8 bit register (256 possible values). Translating this to python, with a brute force loop:

<br />
a = &quot;b5b586b4f4b3f1b0b0f1ed80bb8fbf8dc68587c094818c&quot;.decode(&quot;hex&quot;)</p>
<p>for key in range(0, 256):<br />
        s = ''<br />
        for i,c in enumerate(a):<br />
                m = ((ord(c)^key) + i)&amp;0xff<br />
                s = s + chr(m)<br />
        print key, hex(key), s</p>

And since all flags always have a flare-on.com suffix, we can just add a grep:

<br />
$ python brute.py|strings|grep flare<br />
219 0xdb [email protected]<br />

So the flag is [email protected] and the key is 219 decimal (0xdb).