ELF x86 — Fake Instructions Rootme (Cracking)

Hariharan@Blog:~$
5 min readJul 20, 2023

--

INTRODUCTION

This is an easy challenge that took me some time to understand what was going on. A tricky challenge, based on fake instruction and fake jumps, designed to deviate us from the flag.

CHALLENGE ANALYSIS

Let’s start with the basic checks.

The binary is dynamically linked and not stripped, but this doesn’t have an impact on this challenge.

Next, we check for any clues using strings.

We find something interesting. We find some junk characters, which is usually how flags look like. The second one is “sh 3.0 # password: %s,” so somewhere in the code %s is going to be replaced with some string.

%s tells printf that the corresponding argument is to be treated as a string in c language.

We run this binary in the terminal and check the behavior.

We can see that the program expects a command line argument. And when we provide an argument it gives the message.

We load this binary in gdb-pwndbg and check for all the functions in the binary. This would be useful for further analysis.

We see some interesting functions like ‘WPA,’ ‘blowfish,’ ‘RS4,’ and ‘AES.’ Is the password getting encrypted/decrypted using these functions? Let’s analyze further to find other clues.

We check the main function using IDA as well as the ASM code in GDB. Line by line explanation of the ASM code can be found on my GitHub.

We can see the disassembled code in IDA.

We can see that this program expects an argument. That explains the behavior of the program in the previous image.

Then there is a malloc allocation followed by a memcpy. There are certain array operations done to v5. At this point, we do not know what v5 is. ‘Strcpy (v7, v4[1])’ says that something is done with our argument (v4) and copied to v7.

One way to solve this would be to trace back the message we received earlier and see how that came about.

Alternatively, we could analyze the main function and observe ‘function_ptr_2175,’ which points to the WPA() function.

Let’s analyze the WPA() function using IDA. Again, the WPA ASM code can be found on my GitHub.

There is a string compare function that calls the ‘blowfish()’ function; otherwise, it calls the RS4 function. So let’s see what these functions do.

RS4 Function
blowfish function

We can see that the RS4 function prints the ‘default’ message when we give the command line argument. So this tells us that the program never goes inside blowfish() function. We need to bypass this ‘if and strcmp’ condition to activate the blowfish() function. The blowfish() function performs a series of operations that could lead to our flag.

CHALLENGE SOLUTION

In order to see what’s happening in the WPA() function, let’s set a breakpoint when the function call occurs. We’ll conduct some analysis to find out where the function call happens. (Refer to the GitHub link).

Let’s set up a breakpoint at “call edx” and run the program with some argument.

Breakpoint at “call edx”.

gdb-pwndbg shows that there are some arguments. Analyzing the esp register could give a high-level detail about the variables.

So one of the variable contains our argument and other one has some weird characters and stored in the stack. This is the same junk we saw in ‘strings.’ Continuing with further instructions, it hits the RS4() function and doesn’t go inside the ‘if (!strcmp(a1, a2))’ to activate the blowfish() function.

So let’s set up a breakpoint at “if (!strcmp(a1, a2))”. Again refer to the Github Link for understanding the ASM Code.

The ‘test eax, eax’ instruction performs a bitwise logical AND operation between the value stored in the ‘eax’ register and itself (eax & eax). Its purpose is to check whether the value in ‘eax’ is zero or not.

The ‘test’ instruction sets the ‘zero flag’ (ZF) based on the result of the AND operation. When the result is zero (all bits are clear), the zero flag (ZF) is set to 1. Conversely, if the result is non-zero (any bit is set), the zero flag (ZF) is set to 0.

The ‘jne’ instruction checks the zero flag (ZF) and jumps to the address 0x804870f if the zero flag is not set (ZF = 0). In order to set the zero flag to 0, the value in eax should be 0.

Setting a breakpoint at “test eax,eax”

Registers clearly show EAX = 0x1. This should be set as 0x0 (Zero flag) to bypass the if condition and activate the blowfish().

Using “set $eax = 0” will set the zero flag = 0. Let’s continue the binary using “ni”. using “ni” 3 times will reach the blowfish() and get us the flag.

And there we go! We have our flag.

Hope you understood the challenge. Do check out my other blogs.

Don’t forget to give some claps if you reached here :) Follow me for more write-ups.

Goodbye:)

--

--