“This room is dedicated for the RE challenges, each challenge has unique concepts divided in each binaries. As if now only phase 1 is added will decide about phase 2 on response. Developed by WhiteHeart and tested by IslaMukheef”
In this TryHackMe room you will be tasked with cracking various executables and in each level the challenges gradually increase in difficulty. This will definitely test your skills as a reverse engineer.
Like every reverse engineering CTF, I started things off by pulling strings from the executable to see what catches my eye. After seaching for strings in Ghidra I found 1 string that looks like a flag that was referenced in the function FUN_00401410 and address 0040142b and 2 that look like an output string after a comparison is made between the correct string and the users input, 1 more string that tells the user to enter the flag.
After navigating to the address where the “Enter The Flag” string is referenced I am now presented with what you see blow in the decompiler. After analyzing the information I was able to deduce that
char local_40 ; must be the variable that holds the users input since it is only allowed 20 bytes and the flag itself is 18 bytes. There were also a few empty functions, but looking towards the bottom we can see the same function where the flag string was referenced.
After heading to that function I was presented with this in the decompiler. It’s safe to assume that this must be the flag check function. On line 9 and 11, it looks like the author of this program created callback functions that act similarly to how the strcpy and strcmp functions work.
I went ahead and renamed the functions accordingly as you can see below. On line 9 the flag string is copied into the variable local_28. On line 11 the strcmp_callback function is used to compare param_1 (the users input) to local_28 (the flag variable). If at any point the users input gets null terminated in the comparison process the string “Dont Worry its a start ;)” is printed to the terminal, if the users’ input and flag variable match, the string “That was easy…Bruh!!!” is printed to the terminal.
Again I start off by pulling strings, and come across a string named “Thats your lucky number !!!” which is referenced in function FUN_00401410.
After heading to the function where the string was referenced I was presented with this code in the decompiler, as you can see the function takes a parameter as an integer if the parameter is equal to the hex value on line 5, we get the lucky number string that was referenced. All we have to do is convert the hex to decimal to get the answer.
After pulling strings from the binary I found one interesting string “Wow Ur At L3?” after navigating to the function where the string is located (FUN_004014cb) I was presented with this in the decompiler.
FUN_0040147f on line 13 is just an empty function. FUN_00401410 leads to the function that creates the flag string. After navigating to that function, I was presented with this code in the decompiler. I converted all the local variables from hex to ascii to see what value is returned, after doing so I was given the ascii value:
1_3L02_shT_t1L_3t13. So I tried entering that as the flag and it was incorrect so I figured each hex value must be reversed. After reversing the ascii values and running it against the executable, the program printed the “Get Ready For L4 ;)” string along with the correct flag.
Another method of solving this task would be switching the
JG instruction. at address 004014d9 we can see there is a comparison between the hex value 0x1 and the 32bit value located at the address
[EBP + param_1]. On the next line we can see if 0x1 was greater than
[EBP + param_1], then a jump is made to address 004014f2. If you change the JG instruction to JNE or JNZ, the program will move the function that prints the flag since the conditions have changed.
Now that the jump instruction has been changed, the decompiler should read as follows:
After pulling strings I found the string “Rooted !!!” after heading to the function where the string was located, I was presented with this in the decompiler. Apon examining the code in the decompiler, I was able to make an educated guess at what the functions and variables are. Below are before and after images.
I only renamed the functions and variables that seemed important to me also I wasn’t entirely sure what local_28 is and what line 13 of the code does, but I was still able to solve the challange without knowing what they are. As for the xor_string_func was able to come to the conclusion that this was an xor function seeing how the program behaves in a debugger. I felt the most logical place to set a breakpoint would be at the start of XOR function that way I can see the flag string before it gets ciphered. The XOR function begins at the address
00401410. In x64dbg hit Run until the program reaches the point where it asks you to enter the flag, after entering the wrong flag, step over to the next instruction until the debugger jumps to the XOR function breakpoint. From there continue to step over until you see the flag in the EAX register.
Alright, so this time pulling strings returns nothing of value but when executing the program it prints this in the console “Amcm↨QBuYP+lD↨V1pvYBdR” just by looking at this string I can tell it is being encrypted by an algorithm at some point in the program. So I figured since the string is being encrypted and printed to the console, I could see where the
printf function was being used in the program. In Ghidra click on “Display Symbol Tree” and search for and click “printf” from there follow the XREF’s until you land at the function where the printf function was used (FUN_00401453).
Once I arrived at the function where printf was reference, I was presented with this in the decompiler. After analyzing the function and comparing it to the programs behavior in the debugger, I was able to make an educated guess at what each variable is. Below are before and after pictures of the function.
It looks like the function gets the length of the flag, performs a preliminary check on lines 10-11 if the string meets certain requirements, the encryption algorithm is ran against the flag string. Skipping ahead a bit, if you set a breakpoint at the start of the address where the function is located (00401453), the flag will be displayed in memory before it is run through the encryption algorithm.
That concludes this write-up if you have any feedback, feel free to comment. Feedback is always appreciated and will help me learn and grow 😊.