Hacking Series Part 11
Category: reverse engineering
We are given a binary called “need-for-speed”. When you first run the program, there is no needed input from the user. The program simply starts generating a key, but exits before the process is finished with the message “Not fast enough. BOOM!”. When I opened the program in IDA, I saw that there were four main functions that controlled the program logic.
The header
function is only responsible for printing the banner when the program is first fun. If you look inside set_timer
, you will see that there is a signal set up to terminate the program after a certain amount of seconds has elapsed. This is responsible for the exit message shown earlier, since the alarm went off before the program was done generating a key and printing a flag.
We need to figure out what determines how many seconds are set as the alarm. If you look at the set_timer
function above, it seems to always set rbp+seconds
to 1, which means this number is static — we will always have exactly 1 second to run the program, generate the key, and print the flag. It is likely that 1 second is not enough time to do all this, which means we will need to find another way to get the flag.
Next, if you look inside the get_key
function, you will see that there is actually another function called generate_key
that is responsible for the key creation. Within this new function, there is a loop that essentially continues for a long time until a certain number is reached, which is the key. This number is 0ED0CC64Ah (hex). Knowing the key may be useful for the future if needed, but since the user doesn’t actually need to input the correct key, it may not be that useful after all.
After this, we finally move on to print_flag
. This function is responsible for calling a decryption function decrypt_flag
, then printing the resulting flag. In decrypt_flag
, there are a lot of instructions that are used for decryption and it would be very time consuming to try to understand exactly how each character of the flag is changed.
Instead, I tried to find a way to bypass set_timer
and continue execution after it. Realistically, we only need to call get_key
and print_flag
in order to get our decoded flag. The function set_timer
has no influencing variables or parameters that other functions rely on, so it should be possible to skip over it.
To do this, I opened the binary in gdb and set a breakpoint before the execution of set_timer
. Then, I used the print
function in gdb to directly access the two functions needed in order. get_key
took a couple of seconds to complete, then I called print_flag
. This gave me the decrypted flag.
PICOCTF{Good job keeping bus #24c43740 speeding along!}