TryHackMe | Reversing Elf Challenge

In this blog post, we'll dive into the TryHackMe Reversing ELF Files room, which consists of eight distinct challenges designed to sharpen your reverse engineering skills. Throughout these exercises, we'll explore how to analyze and deconstruct ELF (Executable and Linkable Format) files, gaining insights into their structure and behavior.

We will showcase the powerful tools RADARE2 and GHIDRA, highlighting their capabilities in the reverse engineering process. Additionally, RADARE2 shares a lot of similarities with GDB (GNU Debugger), particularly in their debugging capabilities and command-line interfaces. By tackling these challenges, you'll learn valuable techniques for inspecting binaries, identifying key patterns, and extracting useful information—all crucial skills for CTFs and real-world penetration testing scenarios.

Let's get started on the path to mastering ELF file reversal!

Crackme1: Let's start with a basic warmup, can you run the binary?

In order to complete this warmup challenge, you only need to provide an executable parameter with CHMOD to the binary and run it:

Crackme2: Find the super-secret password! and use it to obtain the flag

To complete this challenge I looked at the file details itself, it is important to observe that this binary is “not stripped” which allows us to later discuss viewing the functions embedded in the binary itself and better decompile it to understand its purposes.

Then added an executable permisison with chmod, ran the binary to find it accepts one argument, and tested to see what the outcome is. In another terminal I used the strings command line utility to filter on pass as a potential easy-win and it worked.

It’s important to keep in mind the value of the lesson with this simple scenario- you are able to extract phrases that may be in clear-text in the binary with this utility or filter on certain keywords. A great way of finding anything between the phrases flag{} is by using: strings binary_file | grep -o 'flag{[^}]*}'

Crackme3: Use basic reverse engineering skills to obtain the flag

To solve this one, we are using the same skillset as previous. This time manually inspecting the output of the strings utility to see that we can find a mention of ‘correct password!’ and a base64 encoded text prior to it. We can decode that output with echo and base64 and find the flag.

Crackme4: Analyze and find the password for the binary?

This time we have to dig a little deeper. When we run the binary we’re getting a hint “This time the string is hidden and we used strcmp”. Notice running strings does not deliver an easy win this time too. STRCMP is a C built-in function that compares two strings, our input and the correct string.

We have a couple ways of solving this. You could use R2, LTRACE, or GDB. I am sharing the solutions with LTRACE and Radare2 (R2) below. The hint mentions IDA / R2.

Running LTRACE against the binary and providing a required argument to ‘test’ against the binary. This works because of the dynamic debugging capabilities of the command line utility.

Another way of solving this is by feeding the binary into the command line utility Radare2 (r2) an open-source reverse engineering framework to analyze the binary in debugging mode. This allows you to step through the execution of the program, set breakpoints, inspect memory, registers, and more. Similar to GDB (GNU Debugger).

We start by specifying debugging mode with -d, running aaa to analyze the binary, and afl to list all the functions. We can see there is a main function so we can run pdf @main to dissasemble the main function and see whats going on.

The results of the main function are below. We can see that there is a “call” to '“sym.compare_pwd”. That is human-recognizable (not very obfuscated) so we could continue to disassemble there to look for more indicators of a potential to pull information we need.

This does confirm it is what we’re looking for, we see the “strcmp” mention yet again. We can create a breakpoint at that place in memory by using the db flag with the specified memory address circled below. Then we will provide an argument in “open debug mode” with ood of test to see how it responds. Then we send dc to run until the breakpoint where it will pause in its execution for us to see how the program responds.

Following through on the above, we can re-examine the function of comparing PWD. We see where that memory address is there is a “b” signifying a breakpoint. Now we can run px @rdi. This will inspect the memory address stored in the RDI register.

px prints raw memory in hexadecimal format and @rdi will print memory “at the address of” the target (rdi register). The RDI register is typically used to hold the first argument in a function call in x86_64 architecture. So we’re able to use this after stopping at a breakpoint to check what data is being passed to a function via the RDI register, or to inspect values like user input, memory buffers, or pointers to data structures.

Crackme5: What will be the input of the file to get output Good game ?

The hint for this one is the same IDA / Radare2. You are able to use LTRACE again to automatically spit out an answer for you against this binary as shown below, providing an argument to obtain the flag.

We can replicate the previous methodology to obtain the same results. Notice we’re able to find a STRCMP (string compare) statement in the disassembly of MAIN.

We can create a breakpoint here. Provide an argument like ‘test’ and examine the main function again.

Don’t forget to use ood ‘argument’ to provide an argument so you don’t need to do what I did below and add ‘test’ randomly there.

Notice I examined the values stored in the RSI instead of the RDI. You can obtain the same information from either, it is important to recognize the value of reading both memory registers. The RSI is typically used to hold the second argument passed to a function. This can help you understand what data is being processed by the program.

Crackme6: Analyze the binary for the easy password

This particular challenge spits out the following when you run the binary “Good luck, read the source”. This pushes us a little more toward the National Security Agency (NSA) tool GHIDRA or IDA to read the source code of the program. IT is possible to solve this doing what we’ve been doing though with RADARE2 (R2).

I am going to be using the tool GHIDRA. You can import the file into Ghidra, let it analyze the “malware/binary whatever” with all the default options and then we can start looking around.

Click on “main” in the right window to examine the contents of the main function. Then we can scroll up slightly to find “compare_pwd” which sounds like “compare password”. If we click on that particular function and go to where its homed we can drill down to look for this function in our Symbol Tree.

In the Symbol Tree we can see where comparepwd lives. Then find a “call” to ‘my secure test’ and click that to go deeper.

We can find a CMP piece to the my secure test function: cmp al, 31h ; ‘1’. This assembly instruction performs a comparison between the values in the AL register and the hexadecimal value 31h which represents the ASCII character ‘1’.

In x86 assembly the CMP instruction is to compare two operands without modifying them. This will repeat until it accounts for every character in the string against the correct string.

We can send this function to the Decompile section of GHIDRA by going to Window > Decompile (video demonstration: https://www.youtube.com/watch?v=Iny6vzT-C_Y) and find the clear-text password we’re looking for in the source as the hint suggested earlier.

We can confirm the solution and submit it to obtain credit.

Crackme7: Analyze the binary to get the flag

We are able to solve this one once again in a variety of ways. Executing the binary provides multiple options for what it accepts.

After automatically analyzing the file- we can disassemble the main function and see there is a giveFlag(); function.

To trigger this we can send the hexadecimal value of 0x7a69 which is 31337 as an argument and we will be able to obtain our flag. It sounds like this was expected to be solved using IDA or RADARE2 (R2) though, lol.

We can see this in RADARE2 as well, notice the comparison function pointing to an address accompanied by ‘Wow such h4x0r!' and giveFlag short after. We can send that to a HEX to DECIMAL convertor and get the same 31337 number.

Crackme8: Analyze the binary and obtain the flag

This challenge is similar in nature to the previous challenge. I will be using both GHIDRA and RADARE2 to solve this one. Below is the expected functionality of the file:

Same protocol. Import that file into GHIDRA and analyze it. Then start looking into the disassembled main function for anything indicative of a lead. Upon opening the main function we can see that a function ATOI exists with puts(“Access granted.”); nearby it.

The ATOI function exists typically in the C programming language for converting strings into an integer representation. We can convert the address of 0x35010ff3 to hexadecimal to get the number -889262067 and we can pass that to our program to obtain the flag.

We can see that in RADARE2 as well, then convert that number to the same numerical expectation to get the flag.

And there you have it! We've just scratched the surface of the Try Hack Me Reversing ELF Files room, diving into some wicked challenges that sharpen our reverse engineering skills. With tools like RADARE2 and GHIDRA, you've got the power to break down ELF files and see what's really going on under the hood.

Remember, every bit of knowledge you gain brings you one step closer to conquering those CTFs and tackling real-world pentesting challenges. Keep experimenting, stay curious, and don’t forget to have fun while you hack away. Until next time, happy hacking!

Previous
Previous

x86-64 Basic Buffer Overflow Theory

Next
Next

Wireless Penetration Testing: WPA2-PSK