In this challenge, there is elements of Packing and Bit Shifting, with a little twist in it.
Running “file” on the binary, we see that it is statically linked
This means that all the functions and libraries are embedded within the binary itself, and does not call and link any libraries from the OS dynamically . This also means that we cant run “ltrace” on it.
When we run the binary and enter any string, it shows us it’s a wrong password before prompting again
When we run “strings” on the binary, we see that it ends with “UPX!”. This means that it’s a packed file, and analyzing it would probably yield no useful results. We proceed to unpack the binary:
Now when we run “strings” on it again, we see more useful stuff, particularly the part where it prompts us for the password, and a long string of numbers
Passing those number through CyberChef and playing with different string manipulation functions yields nothing useful. Entering the entire string to the binary as a password is false as well. We now pass the binary through Ghidra, and see what can we dig up.
The first thing we want to do is to find the string “Enter Exatlon Password”, and see which memory address references it, so that we may observer what is happening within the binary.
We see this block of code that references the string in 0x00404cf0, and does some operation before calling the function named “exatlon” in 0x00404d24
Ghidra has this nice functionality where on the right side of the UI, it breaks down the code into a more human readable format
Looking at this piece of code, it becomes more apparent at what it’s doing. Roughly, it takes user input (line 27), passes it to the function exatlon (line 28), and does an “equals” comparator between the output of the exatlon function, and the string we saw earlier (line 29). We thus need to find out what the function exalton is doing, before we can reverse what input we should put in to match the string.
Double clicking on the function exatlon and referencing the right pane again where it breaks it down into a readable format, we can see what this function is performing.
On line 28, its a while(true) loop, and it iterates through every single character in the string entered (string pointer is likely local_78, which is incremented at the end of the loop)
Looking at line 39, we see a shift left of 4 on each character. What a left shift of 4 does is to multiple the number by 2, 4 times (i.e. x *2 * 2 * 2 * 2). This happens on each character, more specifically, their ASCII value. Therefore, to reverse the input required to be entered for it to match the string of integers, we need to shift every value right 4 times as well, which is to divide every number by 2, 4 times. We do this with a simple python script, and we actually get the flag itself!