This is the third part of smash the tux series, in this post lets continue our work and try to finish 0x03 - 0x06 challenge
Challenge 0x03:
from this source code, we can see that there is a limit of input length in the program. If we try to input with a length that exceeds 512 bytes, the program will terminate itself. We can safely assume that 512 is the length that we need to overwrite the EIP register
let's try to test the program by inputting just 512 bytes and see what happen to it.
so what happens in here?
this vulnerability is called "off by one byte"
if the programmer knows that it takes 512 bytes and above to overwrite the EIP, they should not put a check like this (strlen(text) > 512) that means we can still input with length 512, to do the correct checking it supposed to be like this (strlen(text) >= 512)
this will make sure that input with length 512 and above is properly sanitized
Let's try to determine how much length we actually need to control the EIP register of the program it looks like it is located at the 488th position
By creating a simple python script with the following logic we can see it is working. Let's try to create a payload and remember the program is equipped with NX protection that means we need to construct a retlibc payload.
From this information, we can launch our exploit inside the GDB and we got a shell
we can also do it outside of the GDB cool :) we passed the challenge
Challenge 0x04:
now, this is pretty cool!
ok so the program is pretty simple, you create a file with a bunch of string inside it and passed the name of the file as the parameter in the program then the program will read first two bytes of the file and treated the size of the file content.
why two bytes?
because the sizeof(uint16_t) is equivalent to two (google it)
fread() will take this value and stored it in variable "len" which is inside the struct variable "foo"
before the content of the file is stores in variable "content" which is also inside the struct variable "foo" it gets a length check. If the length is bigger than 1024 it will print "bad dog!"
so how do we bypass the length check?
easy! we overflow the integer variable since we have total control on the first two-byte right?
so this is how we do it
we know that the max value of uint16_t is 65535 this is equivalent to 0xffff in hex and as you know at the length check the value was increment by one right?
because the value is too big to store in the uint16_t it will scrap back to 0 thus bypass the length check
so if we try to create a file with the following python script:
we are able to overwrite and take control of the EIP register.
Now, something interesting just happens when I try to create an exploit with this script.
you can see that I append the system function address after the padding this will execute the system call but because there is no parameter it will cause segfault. But take a look again at the error it says that the program tries to execute "r" command
how this is happening?
if you try to load the exploit inside the gdb and observe the stack at the end of function "foo_cpy" there is a character "r" that will act as the first parameter of the system function. This can be caused by the operation of the program in the stack you don't have to know the detail but you just need to be aware of this condition.
we can try to make a program that executes shell command with the name "r" by putting a symlink on it and try to put the path of the program into the environment path so when we execute the exploit the vulnerable program will execute the "r" program that links to "sh" shell, like this:
or like this:
cool! we got a shell :)
Challenge 0x05:
the program is pretty straightforward it only executes a system call with the parameter "ls -l /home/tux" this basically listing all of the files and directory inside the home directory.
but this program has a little bit of a problem it calls the "ls" utility dynamically which is rely on the environment path rather than using full path like "/bin/ls". An attacker can just alter the environment path to be redirected to the forged "ls" command, like this:
then create a new ls file(it doesn't matter what type of file that you created as long as the name is same and it's executable):
~# echo "/bin/sh" > ls
~# chmod +x ls (we want to make this file executable)
so when the program executes it is not calling "ls" utility that comes from default directory but it executes forged "ls" utility that we just created earlier that execute "/bin/sh"
Challenge 0x06:
we can analyze that the program has a size limitation of 64 bytes then it sends our input data to the variable buff using sprintf() and print the content using puts() function
to take control of the program we can trigger the buffer overflow by using the format string vulnerability in the dummy function since it plainly passed our input to puts() function
we can do this by passing "%76xAAAA" this means that we want to extend the length of our input using format string into 76 bytes and we add 4 char of "A" to see that we are able to overwrite the EIP register. By checking the log from "dmesg" log we deduce that we successfully take control of the EIP
you can do analyze this input more thorough also via gdb:
now all that's left is to craft a retlibc payload since the binary equipped with NX protection.
run the exploit we got a shell inside and outside the GDB
Cool! so that's all folks
I hope you enjoy this blog and see you in the next post about smashthetux
Comments
Post a Comment