DEV Community

Nucu Labs
Nucu Labs

Posted on • Updated on

Root-Me: ExploitMe – Basic Buffer Overflow

Hello,

In this article I present you the solution to nice and short cracking challenge from Root-Me. After opening it up in Ghidra, I saw that the challenge is easy to solve, all you need is to find the password, which is in plain text. Basically just copy paste and you get the flag, but wait, there’s a twist!

I should have learned my lesson from the other challenge from Root-Me, which also had a twist.

I feel ashamed that I didn’t observe this, just like the password everything was in plain sight 😦

bss section of the binary

See what I mean?

function_ptr.2175 is a pointer to a function and in the program’s main it is made to point to the auth‘s address, then it’s called.

0804869e b8 f4 86        MOV        dest,auth
         04 08
080486a3 a3 f4 a0        MOV        [function_ptr.2175],dest                         = 00000000
         04 08
Enter fullscreen mode Exit fullscreen mode

And, if we inspect the auth function, we can see that it calls the asm function if the password we provided matches.

cmp_ret = strcmp(buff,dest);
   if (cmp_ret == 0) {
     _asm_();
   }
Enter fullscreen mode Exit fullscreen mode

We can input the right password and get the flag, that’s what I did at first, or, we can do a simple buffer overflow exploit in order to force the program call the asm function directly.

The function pointer and the buffer are located in the .bss section of the binary. the .bss section contains uninitialized objects, in our case the global and static variables.

Somehow, the compiler decided to place the function pointer right after the buffer, the buffer on which the following piece of code gets executed:

strcpy(buffer.2176,argv[1]);
Enter fullscreen mode Exit fullscreen mode

The buffer is only 146 bytes wide and at 146+2 starts the function pointer, this means that we can control what’s written in the function pointer if we can overflow the buffer.

We can do that, because, strcpy continues to copy values into the buffer unless a NULL terminating character is reached.

What we need to know now, is the address of the asm function. Which can be easily found. Either look at the dissembler view or use the nm tool.

➜  /vagrant nm Exploit_Me(if_you_can)
 08048731 T asm
Enter fullscreen mode Exit fullscreen mode

If we construct a payload that outputs ‘x’ 148 times to overflow the buffer and then append the asm’s address to it we successfully exploit the binary:

➜  /vagrant ./Exploit_Me(if_you_can) $(python -c "print('x'*148+'\x31\x87\x04\x08')")
 [+] Felicitation password de validation de l'épreuve:: <redacted>
Enter fullscreen mode Exit fullscreen mode
  • $() – spawns a new shell
  • python -c “..” parses the program as a string

The ./Exploit_Me(if_you_can) binary will get the output as the first argument and that’s it! The buffer overflows, the function pointer gets overridden and the program executes asm instead of auth.

function_ptr.2175 = auth; # Had this been after the strcpy things would have been different.
strcpy(buffer.2176,argv[1]);
*(undefined *)((int)dest + 8) = '_';
*(undefined *)((int)dest + 9) = '.';
iVar1 = (*(code *)function_ptr.2175)(buffer.2176,dest);
Enter fullscreen mode Exit fullscreen mode

In case you’re wondering why is the asm address written as ‘\x31\x87\x04\x08’, it is because we want it in little-endian format. In big endian the address is 0x08048731.

asm function's disassembly

The asm function is quite complicated, it decrypts the flag, the magic here is that it doesn’t depend on the program state or any arguments, thus if we manage to execute it we get the flag directly.

You can also solve this challenge in other ways, check the solutions on Root-Me for more creative ways in solving this crackme.

Thank you for reading!

Top comments (1)

Collapse
 
ondrejs profile image
Ondrej

Nice article, thanks!