For this challenge we’ve been provided with a binary in .exe extension. Analyzing it, using the command file or some softwares like Ghidra it was possible to discover some basic information like it is a Portable Executable compiled in Visual Studio, it is a 32bit application working on Intel 80836.
So, executing it using the command line we see an introduction text followed by a prompt waiting for our input:
So our objective is to digit a series of letters in the required order, providing the right ingredients to the program. Trying manually it is possible to discover that the first correct choice is the letter A, but once it has been chosen it is impossible to continue with any other letter. We assume that some actions are required to go on.
We’ve tried to input a string of many character to see if some errors could have been generated, but nothing happened, since the program only reads the first letter of our input: we can suppose that a getchar function has been used.
At this point we have to reverse engineer this program to discover what it wants us to do: so we loaded it on Ghidra since it also provides a screen with a sort of C code generated starting from the assembly; it makes way more clearer the intents of the program. Being not able to provide the .gdb file, the names of the functions and other symbols are replaced with generic names.
We know our entry point is at 0x00401a08, so the research starts from there. There are different calls but the one that is important is that specific one that uses as arguments an integer pointer and an array of strings. The argc and the argv are recognizable there. Doubleclicking on it we get into the main, recognizable since we also find the introductory text that we’ve seen before:
Suggestion: as soon as something new or familiar will be recognized, it is good to rename it so it is easier to remember what that particular variable or function is supposed to do. Most of the names in this writeup have been modified.
So we jump right at the end of the introductory text and encounter a switch that will work upon a counter that will be incremented, and will compare our input with the first five letters of the alphabet in a particular order:
We can notice the lines:
if (my_input != 'A') goto switchD_004015ae_caseD_5; if (my_input != 'E') goto switchD_004015ae_caseD_5; if (my_input != 'B') goto switchD_004015ae_caseD_5; if (my_input != 'D') goto switchD_004015ae_caseD_5; if (my_input != 'C') goto switchD_004015ae_caseD_5;
and understanding that the goto redirects to a portion of code that will give us a message error and will quit the application we discover the order of the five inputs that we’ll have to provide: A E B D C.
Actually, inputting the E as second character will make us fail to get the flag. So we inspect the function in the case 1 of the switch (that we’ve renamed as add_ingredients).
In that function it is possible to recognize the call to a scanf that is done on a file called items.txt, so we create this particular file and try to insert the E as second input. it works now, but clearly it is not possible to proceed with any of the third input, because something needs to be written inside the file that then will be read by this function. At a first glance, we see some strings that could be used and on which some comparisons are executed:
- Bigfoot nail
- Unicorn hair
- Dragon teeth
and these names are into a do-while cycle that works on a counter of 3 values. So we know that the file will have to contain 3 of these values. Let’s try to write the first three into the file and let’s see what happens inserting the third input, the letter B:
Again, it is impossible to continue without inserting the right ingredients of the potion. So we try to insert different ingredients and in different order and we discover that the message of error is displayed in the exact moment in which a wrong ingredient is shaked: now we know most of the things we need and considering that the order of the ingredients is the one listed above and the first two are correct we only have to find the third one: we use Sugar and we are able to continue; inputting the last two letters, D and C we can generate the right potion and get our flag: