Next is another write up for CTF challenge Delloite Greece, I got it also from my classmate (Thanks, Cristos)
in this post, we are going to take a look at how to solve the "doom admin challenge".
Note: the doom admin has a two-part challenge, first is reverse engineering and pwn. This post will describe how to solve these two challenges
so we got an ELF 64 bit binary and to make this more similar to the real event I decide to run this binary in my virtual machine.
I just going to loop the binary and it turn out the binary itself open a port with number 666
make a connection to the server and it gives us the following prompt. We choose shell options and input a random password but it doesn't give us any further information
when we checked again to the vm it shows a segmentation fault
for further investigation, let's open the binary at Ghidra.
when we go down at the main function we can see a similar banner that shows a welcome message in the previous figure and after showing the banner the main function called the menu() function.
in the menu function, the program itself only offers two options you either choose 1 for shell and 2 for an exit. Prior to choosing one we can see that there is a local variable called "local_9" that was hardcoded to 'n' and our input is passed to get_key after calculation the length.
if the key is matched it will compare the local variable "local_9" to character "y" and if the variable matched it will call the shell. At first, it may be impossible to get to the shell since the variable is hardcoded. Well not really we are going to talk about this later in this post how to circumvent the check using the buffer overflow.
let's take a look at the get_key() function first.
At first, the get key function to try to check if the environment variable "CHECK" is contained "REMOTE" value and if it's yes it will call localhost port 11525 and get the file name "get_shellf_service_key" to retrieve the content
if the environment is not set it will get the .password.txt file. No matter what flow of the function both of the choice will compare against our input.
Actually, we already get the first flag, it turns out that the URL ("http://127.0.0.1:11525/get_shellf_service_key") is not mapped to the localhost but it's mapped to the universal address "0.0.0.0" this means that we are able to go to the URL get the first flag directly.
Note: we already verify that this flag is correct and when we test this in the real platform it also shows the same result.
now move to the pwn part
lets set up the environment to be as similar to the CTF environment.
you may notice that I add two files according to our analysis which is get_shellf_service_key and .password.txt
also, don't forget to set the environment variable "CHECK" to be "REMOTE" please be aware that the program is running in port 666 which is considered as a privileged port it needs to run in sudo so we must change to root account first, added the new environment variable and then run it again
and also to mimic the URL I used the python simple HTTP server to setup the service.
now if we go to the service this time we can fully interact with the service without crashing it.
so as you notice that the local variable "local_9" is hardcoded to "n" so even though we got the right password we cannot get the shell
we can circumvent this process by overwriting the variable local_9, but how?
let's go back again to the menu function again and analysis it again one more time if there are any recv functions that vulnerable to buffer overflow.
so we are aware that there are two input from the program, the first input seems to be not vulnerable to buffer overflow since it's buffer is allocated correctly, the variable local_818 allocated 1024 bytes and recv function also allocated 1024 bytes(400)
but in the second function here we can see that the allocated buffer of recv is bigger (0x800) than the allocated buffer of local_418 able to handle (0x400)
another thing you need to aware is that the get_key function comparison, we need to supply the correct key in order to go to the intended part of the program shell function
notice that the comparison in get_key function is using strncmp which is using the length of our input this will render our exploit to be useless since we cannot overflow the stack.
(in the menu function the length of our input is calculated and then passed to the get_key function and then the length of the input is used to compare against the password)
so what should we do to circumvent the string length check?
I take my time and try to look some way to bypass strlen check and in this post (https://github.com/VulnHub/ctf-writeups/blob/master/2015/tjctf/rot13.md) it is said we can circumvent the length check by append "\x00" byte in our input since strlen stop calculating length until it reaches null bytes
so we combine it with our password to be like this:
"CTF{797b77a58f3e01d620675f9e39c22347}" + "\x00" + <payload>
so when it's passed to the get_function key only the flag is checked but the payload is still carried to the stack so we can overflow the variable.
the next thing we need to know is how many padding or offset for the payload to rewrite the variable "local_9"?
here is the POC that I could come out
you can use this python script to automate the process (the pattern is generated to be 1050 characters)
after that, you need to attach the gdb into the process of doom_admin and set the breakpoint at the if (local_9 == 'y') code then dumps the register to look at the pattern.
with the help of ghidra we can identify what is the equivalent assembly code
you can attach gdb to the doom admin process in the following way
after that put breakpoint at the if statement, after that all you have to do is run the python script and it will it hit the breakpoint
cool! we able to overwrite the local variable and we can see it is fall into "3Bh4" characters
so we need 1001 characters to overwrite the local variable. Update our script to be like this.
run it and we can examine the register again to check if it's correct or not
hmmm, it seems that our input is appended with "\n" so note for all you guys read function in c is always append the newline character in every input so it may cause an error in our exploit.
now all you have to do is just increase the padding like this
run it again and we got a shell :)
I already check the exploit if it's applicable in different OS or not and yes it can run despite the OS, as long you set the environment correctly.
Hope you enjoy guys :)
Comments
Post a Comment