Hacking Series Part 1
Category: Reverse engineering and forensics
We are given a binary and an image file named “mystery” and “mystery.png” respectfully. Somewhere in these two files is the flag. By trying to view the contents of the binary, it is clear by the header that it is an ELF file and can be executed. To do so, I elevated privileges on mystery in order to execute by using the following command:
chmod 777 mystery
When viewing the contents of the image file (mystery.png) it is clear that it is a valid PNG, but the actual image gives no indication of where the flag can be found. However, when using a hex editor (xxd) to view the contents of the image, I got the following results at the very bottom:
This indicates that the image is used for storing the flag, but the flag itself seems to be encoded since some of the letters are substituted for others. From this, I guessed that the binary is manipulating some letters in the flag by an unknown logic and storing it at the bottom of the image.
Now, all that’s left to do is figure out how the binary works. I opened the file in IDA and immediately saw that the binary required another file in order to successfully run named flag.txt.
I also noticed that the binary opened these two files right away, but with two different modes. Mystery.png is opened with append permissions and flag.txt is opened with read permissions. This indicates that whatever is written in flag.txt influences the result that is appended to the bottom of mystery.png. This can also be seen in the above image, when the variables modes
and aA
(representing “r” and “a”) are being loaded into rdi
, which passes them as parameters in the function _fopen
.
After this, there are a few blocks of assembly that accommodate error handling if these files are not found and can be skipped over since they do not influence the outcome of the flag. The next important block of code starts at loc_1230
in IDA:
The next few lines of assembly seem to repeat themselves, but use different variables. From the first movzx
instruction to the call
to _fputc
, these lines repeat themselves a total of six times. The function being called (_fputc
) is used for writing a character to a stream. The stream in this case is located in rbp+var_38
, which is passed into rdx then into rsi. The character changes after every function call, and is eventually stored in eax then in edi. Essentially, this entire block of assembly writes the first six characters found in flag.txt to the bottom of the image and moves on.
In the next segment, the binary writes a few more characters to the end of the image, but increments and decrements them to effectively scramble the letters.
In loc_1308
, there is a condition for a loop. It compares the counter variable rbp+var_4C
to the hex notation for the number 14 (0Eh). If the counter is less than or equal to 14, it will jump to loc_12DB
and if it is above 14 it will jump to the next instruction, which is in the block on the left.
The assembly for both locations look similar, especially to the assembly seen just before them. This means that they are also responsible for writing characters to the bottom of the image. The main difference is the add
instruction in loc_12DB
and the sub
instruction in the left block. From an index of 6 to 14, characters are being added to by 5 to change the letter by one that is 5 letters after it. At the 15th character, the letter is subtracted by 3 to change it to one that comes three letters before it.
Now it is clear that letters from the index 7 to 15 have been altered. The next set of assembly instructions also seems familiar.
There is another condition for a loop here at loc_135D
. This time it compares the counter variable to the number 25 (19h). If the counter is less than 25, it will jump to loc_133A
. If it is greater than 25, it will close both files and gracefully exit the program. This means that the flag is most likely 25 characters long.
In loc_133A
, the assembly looks almost identical to the previous locations, meaning it continues writing characters to the end of the image. In this block however, there is no addition or subtraction on the letters, which indicates that it just copies the remaining letters from flag.txt and appends them to the bottom of mystery.png. So, from the index 15 to 25, we know that the letters have not been changed.
So far from the entire 25 letter flag, we have the following information:
- Letters 1–6 remain the same
- Letters 7–14 are added to by 5
- Letter 15 is subtracted by 3
- Letters 16–25 remain the same
The altered flag found at the bottom of the image is shown below.
picoCTK.k5zsid6q_fb51c821}
By looking at an ASCII chart, I shifted the required letters by -5 and +3 to get the original string.
picoCTF{f0und_1t_fb51c821}
By inserting the devised string into flag.txt, it outputs the same scrambled string that we had in the first place, which means the found flag above is correct.