binaryBasic Binary Disassembly

Completing a simple reversing challenge

Introduction

In this blog post, I shall be trying to complete the room `0x41haz` on TryHackMe, listed herearrow-up-right. It is listed as a 'simple reversing challenge'; so we shall we be trying to understand what the supplied binary does by looking at its disassembled code.


First steps

The first steps would be to run the file command on the binary, which will provide us some information as to the file type and architecture. For example:

$ file 0x41haz.0x41haz
0x41haz.0x41haz: ELF 64-bit MSB *unknown arch 0x3e00* (SYSV)

We can also run checksec to check if there are any binary security controls in place like PIE or NX.

$ checksec 0x41haz.0x41haz
                                                   Checksec Results: ELF                                                   
┏━━━━━━━━━━━━━┳━━━━━┳━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃             ┃     ┃     ┃        ┃         ┃       ┃         ┃         ┃         ┃           ┃             ┃  Fortify   ┃
┃ File        ┃ NX  ┃ PIE ┃ Canary ┃  Relro  ┃ RPATH ┃ RUNPATH ┃ Symbols ┃ FORTIFY ┃ Fortified ┃ Fortifiable ┃   Score    ┃
┑━━━━━━━━━━━━━╇━━━━━╇━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
β”‚ 0x41haz.0x… β”‚ Yes β”‚ Yes β”‚   No   β”‚ Partial β”‚  No   β”‚   No    β”‚   No    β”‚   No    β”‚    No     β”‚     No      β”‚     0      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Note: This is using the pip version of checksec which is available herearrow-up-right.

Both NX and PIE are enabled. NX enabled means that executable bit isn't set, that is, certain areas of the memory address space are non-executable. Thus meaning we cannot execute data (if we were to supply it, by overwriting the RIP, for example). PIE stands for Position Independent Executable. This is also a binary protection measure which ensures that the binary is loaded into random memory addresses every time the binary is executed (although certain parts of the binary may reside in a static parts of memory).

We can also conduct basic static analysis of the binary and look at the strings within it. For example:

We can see some pretty typical strings in the binary such as calls to the libc shared object etc. However, there are strings which ask for a password and provides different output based on the input. This tells us, most likely, that the binary will feature an if/else statement and will jump to different parts of memory depending on the input provided by the user.


The first protection

Recall from our file command the output:

This is not typical of a normal binary especially this segment of the output MSB *unknown arch 0x3e00* (SYSV). The file here is treated directly as an executable. We need to edit the ELF header in the binary (specifically changing the sixth bit which defines endianness); in this case it is set to the Most Significant Bit, MSB (01 in hex) 1arrow-up-right. We must change this from 01 to 02 to switch it to the Least Significant Bit (where the least-significant byte is put first). This is so that the file can be read properly. We can use a hex editor to do this, such as hexedit or hexeditor.

After changing the sixth bit, we can run the file command again on the modified binary.

We now can see a lot more information about the binary. We are running an ELF 64-bit executable which has PIE enabled (which we verified using checksec). The binary is made for Linux systems and has been stripped. This means the symbol names (such as names of functions, like main) have been removed. This makes reverse engineering the binary harder, but still possible.


Detonation

We can now denote or run the binary to see how it works before we take a look at it in a program like ghidra or r2. This can be done like so:

We get the output above, which we found when analysing the binary using strings. We can now type in a password, and see what the program returns. Of course, we don't know the password as of yet, so we should get an incorrect response.

Typing hello world gives us Is it correct, I don't think so. Clearly we guessed incorrectly. Now to take a closer look at it.


Using Radare2

We can use Radare2 r2 to disassemble the file. We do this with:

We can typeaaa to analyse all the code. The output tells us what that command does. Once we have analysed the file, we can run afl which analyses function lists (it lists all the functions within the program).

Here, we get a list of all the functions and their corresponding memory addresses. Typically, if it is a C program, we will first want to look at themain() function. We can do this in r2 via s main. That will change the prompt to the memory address of the main function.

We can now run pdb which will print the basic block assembly of the function.


Going further

We can see there are a few lines which spark some curiosity.

These lines contain hex values which resemble a password. We can put them together and enter them into the binary.

We get the correct answer and can submit the password as the flag, wrapped in THM{}. We can do that manually, or for fun use sed like so:


Summary

This challenge was very easy, and did not require any binary exploitation. However it provided us with a step into using a disassembler like r2 and showcasing some of the commands used to analyse an executable.

Last updated