‘Hide & Seek’ String challenges from MalwareTech
Hello dear friends! Today we’ll try to solve the string static analysis challenges called ‘Hide and Seek’ where we need to find the flags hidden in executable files. The author of these challenges is MalwareTech, the great & inspirational security researcher! 😊
Basically, in each challenge we have an executable file & the task is to find the correct flag by reverse engineering these file(s). This post is mostly to show the approach, & it’s easy to guess but intentionally I’ve removed some pixels of images where the flag is found & displayed.
For all 3 challenges, there’re important rules that we should follow:
- We don’t need to run the given .exe file but do the static analysis only.
- We shouldn’t use a debugger/dumper to retrieve the decrypted flag from memory. This will be considered as a cheating! 😉
By accepting these rules, let’s start with the first challenge. Here I’m using Ghidra as a tool of choice to reverse engineer the given executables.
Analysis of ‘strings1.exe_’ binary
- Once added ‘strings1.exe_’ in Ghidra project, opened in Code Browser window & analyzed using default options, we see something like this:
- Then in the left sided Symbol Tree view, we observe the list of Fuctions:
- The function named as entry in that list should be the entry point & by clicking on that name, we get the Listing view of assembly instructions & also the Decompile view that represents the equivalent source code in the C programming language.
- By observing assembly, highlighted line in green, & even the decompiled C code we have similar variable passed as argument; now it’s clear that some string is being hashed with call to the md5_hash() function. So, once we double click on the EAX register on the same line of PUSH instruction in assembly view & we’ll get to the first flag!
- Once submitted, we get successful response on the browser:
Analysis of ‘strings2.exe_’ binary
- Let’s open the second ‘strings2.exe_’ in Ghidra, once again we locate to the function named as entry:
- We clearly notice that some hex values being assigned to memory locations in Listing view of assembly instructions & similarly those hex values being assigned to different variables in Decompile view except that the first assignment starts with letter ‘F’ instead of 0x46. So, this sequence is likely be the flag string’s individual characters, as 0x46 (i.e., 70 in decimal) belongs to ‘F’ in ASCII table.
- Let’s find out the flag using simple Python code below which uses all these hex values to get sequence of characters as string:
- Once again, on submission we get successful response on the browser:
Analysis of ‘strings3.exe_’ binary
- This challenge is more interesting because it makes use of different strings saved & bundled from a resource file (.rc).
- Once again in Ghidra, loaded the ‘strings3.exe_’ & we located the entry function, let’s go through the Decompile view on the right side:
- Here, the MD5 is getting initialized at first, then some memory locations being filled with 0 (zero) using memset() function.
- Then the FindResourceA() function finds the location of a resource with the specified type and name. The specified type (3rd argument) is 0x6, so it pointing to resource type of ‘RT_STRING’ which is string-table entry. The specified name (2nd argument) is “rc.rc”, that is the name of resource & the handle (1st argument) is 0x0, means the function searches the module used to create the current process. This function call actually returns a handle to the specified resource’s information block.
- Once handle to information block is returned, the LoadStringA() function takes 4 arguments. The first argument is 0x0, to get the handle to the application itself. The second argument is 0x110 (i.e., 272 in decimal), that says the identifier of the string to be loaded. So, it’s a string identifier within the resource file (which we’ll see next). The third argument is actually a buffer to receive the string or a read-only pointer to the string resource itself. It means the flag string would likely be stored in this buffer. The fourth argument is the size of this buffer, in characters.
- After the string loaded in buffer from LoadStringA() function, it gets hashed using MD5 algorithm, so this further thing isn’t so useful. We actually need to find the string identifier in resource & that thing would actually be our required flag!
- We need to check the .rsrc section for stored string resources using Program Trees view from left side:
- After doing some scroll-down, we encountered the beginning of string-table entry in resources:
- Using these identifiers, we can go down till reached 0x110 (i.e., 272 in decimal) string identifier:
- Finally, on submission we get successful response on the browser:
That was fun! Because as we know, reverse engineering & system’s low-level things become more fun & interesting as we dive even deeper…
With me, I hope you enjoyed this journey of statically analyzing 3 different challenges with their executables! Please share & follow for more future blog posts. Also, I’m curious to listen your comments, reviews, opinions, thoughts or even corrections to improve further… 😇