A few words about the Ph0wn CTF which took place on the 12/13/2019.

A few days ago, some friends invited me to join their team for the 2019 edition of the Ph0wn CTF. It was really interesting even though IoT are as far as possible of being my forte.

Against all odds, I managed to solve a challenge with the help of “Mathias”, a smoke break encounter.

Break my ARM

1 - Reco

In this challenge we find one binary “break”.

Let’s avoid any surprise and check the file.

file break
break: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=4175e617ac346c7d70eeda7fb1560c80f8daf541, not stripped

First of all, determine what we are looking for.
According to the challenge description and other solved challenges, we are looking for a flag in one of two formats :

ph{...}
ph0wn{...}

Having no Rpi or emulator at my disposal (for a IoT CTF I know how unprepared it sounds), I decided to run the usual commands :

strings | grep 'ph{\|ph0wn{'

With no luck.

2 - The big guns

So far all we know is that it’s an ARM binary file and we assume that the flag is not hard-coded or at least, not as its final form.

As a perfect n00b in RE, I fired up the last soft I read about the infamous Ghidra.

Press “i” to open and add the binary to your project then double click on “break”.
Ghidra project
It seems that Ghidra recognized the correct format on its own, then when the message pops up “break has not been analyzed. Would you like to analyze it now?”, click yes > select all > analyze.

Then I’m looking for an entry point, as there is no main function clearly available, I just type “main” in the search bar of the symbol tree window… Lazy yep… But it’s working ! Main function search

Once I’ve got my main function, I’ll look at the pseudo code in the “decompile” window and slowly rename as many variables as I can to make it more readable (using the “l” key). At the end it looked like this : Decompile renamed Let’s be clear, my names are not even always correct and a someone competent would have just read the ASM. But it gets the job done !
Line 37 gives us a good idea of the logic.
The program takes every character of the user input, substract 4 from it (ASCII wise) and compare it to the flag.
Once we know that, a little python can help…

flag = "ph0wn{"
output=""
for letter in flag:
    good = ord(letter) - 4
    output += chr(good)
print(output)

line 1 is our supposed flag format
line 4 we remove 4 to each character of the string
line 6 the flag, as supposedly stored in the binary

ld,sjw

Knowing that, we just have to rerun the “strings” command with our supposed flag.

strings break | grep 'ld,sjw'
ld,sjwkq_d[ukq[^nkga[iu[]niy

3 - Your happy place

Last thing we need now is “add” 4 to each character to reveal the flag.

output=""
good_flag = "ld,sjwkq_d[ukq[^nkga[iu[]niy"
for letter in good_flag:
    output += chr(ord(letter) + 4)
print(output)

And solve !

ph0wn{ouch_you_broke_my_arm}