Sthack 2021 / Baby Octogone
October 15, 20211 - The challenge
The challenge consists of a baby_octogone.elf
file to download and that’s it!
2 - The basics
First let’s get some informations about the file
file baby_octogone.elf
readelf -a baby_octogone.elf
binwalk baby_octogone.elf
Here is a little summary of the most important informations :
- ELF 32-bit LSB executable
- QUALCOMM DSP6 Processor
- statically linked
- little endian
Let’s use strings
to see if we get something:
...
RUsage: %s <secret0> <secret1>
[!] Well done, the flag is: STHACK{ %s%s}
[!] Noooope
Invalid command Line string!
...
It looks like we will have to reverse two secrets that will give us the flag. Maybe a simple concatenation of the secrets will do the job? We will see.
3 - Getting to know the processor architecture
The first thing I read was the Wikipedia page. In the sources we can find some valuable informations about the way the processor works. For example this short presentation.
Now that we have a global idea of how the processor works let’s check the technical documentation given by the editor.
The Qualcomm Hexagon V67 Programmer’s Reference Manual is quite a good start to understant the basics for the next reverse step. Let’s take some time to quickly read it and get the basics of the assembly language.
4 - The reverse
4.1 - What tools to use
I tried to find a way to emulate the processor but I was not able to have something to work within the time constraints.
It looks like we will have to do a complete static analysis.
After some trial and error with the Cutter configuration I was able to get a proper disassembly.
4.2 - The main function
Note: The screenshots contains the already renamed functions because they were taken after the end of the CTF.
The are no available symbols so we will need to do some checks by hand. Maybe finding the function that refers tu the usage string we found earlier ?
Bingo ! We can also see the main condition calling the format string giving us the flag and the “Noooope”.
After a quick analysis, we rename the functions as we think they might work.
NOTE: I renamed the functions “maybe_check_secret_1” and “maybe_check_secret_2” instead of 0 and 1. It was late.
4.3 - maybe_check_secret_1
This function is quite simple, it is a simple string length check and some xor.
Let’s decrypt the first secret:
xor 1732584193 153835079 = 1852732742 = 0x6e6e7546 (nnuF)
xor -271733879 -1618021168 = 1883463513 = 0x70435f59 (pC_Y)
xor -1732584194 -359758933 = 1916034901 = 0x72345f55 (r4_U)
xor 271733878 956840981 = 691693667 = 0x293a6863 ():hc)
===> FunnY_CpU_4rch:)
4.4 - maybe_check_secret_2
This one had me think a bit more.
To put it in a nutshell, the function:
- iterate over the given string AND a data stored in memory at address
50472
- stores in R2 the byte that is stored in memory at address
50216 + the value of the current char
- stores in R3 the byre that stored in memory at address
50472 + iteration number
- compares R2 and R3
- continues if they are equals
Because some values appears multiple times in the memory space used to get R2’s value we might have multiple combinations possible. To get the secret I simply copied the memory spaces used in hexadecimal and made a python script that gives me the possible combinations.
hex_str = '5ef1799f18f8b3c641a0a88e8dbeef273c771b96d986838eca043ce9f808bf05b06edde1a4097db775189eed6566e068662c09142fab72dc565c3648f1f34f9e9a2f0800b05c49bfdc6691156f358bcc83351263f578abb0d687b6042f80ab9b63c18d458a5b5cede91d89e7af31596746a6604cf134da7a961cfc8737f0604c91a9635e5873141ae22995a27c9bf6b08f515d6e5c470a380f7e468edf0ff5122f88debc2e396605a8a267cbc055e18e008d98b367ec8a635c7a760f244777eadd45ceceffcd5b70498a3f9982ffb6ff398005f378d411cb6d4ce7bc4658803584b49fe2000c75ef3a257fa23544a45b1a9eb779d88c042585d569ba66901847'
hex_ref = '2f598a9b5bc14c1c9b45e92fafaf6e'
mem = bytes.fromhex(hex_str)
ref = bytes.fromhex(hex_ref)
out = []
for r in ref:
tmp = []
for i in range(32, 127):
if r == mem[i]:
tmp.append(chr(i))
out.append(tmp)
print(out)
Here are all the possibilities:
- 4nd_easy_ch4ll!
- And_easy_chAll!
- 4nd_easy_chAll!
- And_easy_ch4ll!
4.5 - Build the flag
Because of the second secret’s results they were 4 possibilities :
- STHACK{FunnY_CpU_4rch:)4nd_easy_ch4ll!}
- STHACK{FunnY_CpU_4rch:)And_easy_chAll!}
- STHACK{FunnY_CpU_4rch:)4nd_easy_chAll!}
- STHACK{FunnY_CpU_4rch:)And_easy_ch4ll!}
I assume all of them are valid but I only tried the first one.
I hope you enjoyed :)
Author: Hugo SOSZYNSKI