Find the vulnerability
To begin with, I just played with the binary, trying to find bugs in it… After a few seconds I found this:
Ok, maybe there is something here, let’s open IDA :D (I hate it).
- Framed in red: A few
malloc
declaration. - Purple highlight:
nickname
variable. - Green highlight:
chatbot
variable.
According to the previous picture, we can assume that the heap looks like this:
Ok, so we saw that the program crashes when I enter too many bytes, let’s see how many it takes:
- Framed in purple: Generation of the segfault.
- Framed in red: Offset determination.
If we try to overflow 16 bytes after the nickname, we’re here in the heap:
Read everywhere
Now, let’s try to display an internal string of the binary as botname! I decided to take this one:
Poc:
Hypothesis
Ok so now we have something really great. What would happened if I can overwrite a GOT address with the address of the system() function? It would look like this:
Exploit
Let’s exploit it :)
Bypass ASLR
I need to find a leak in one the libc functions in order to find the libc base address. Then I’ll be able to find the offset between the base address and the system() function.
Leak the __libc_start_main address
There is a well-known leak in the __libc_start_main
function in the GOT. We can extract the adress of this function:
Calculate Libc base address
You will need to display /proc/[PID of Chatbot]/maps
to get the libc base address and calculate the offset:
|
|
Which one of the displayed libc do we need to choose ?
You need to know the system() function address. So your libc base needs to be executable because all the functions in a binary are executable, right ? We can see that only the first one 0xf7dda000
have this permission.
- Framed in red: In the center, you can see the offset determination. On the right, there is the calculation of the libc base address.
- Framed in yellow: Top right, our new libc base address (because I restarted the chatbot binary, the ASLR randomized the addresses). On the left, you can check our substraction, it looks like it works :)
Another tip, the libc is mapped on memory page, so if after your calculation you have an address that ends with 000
it sounds good. The memory pages are 4Kb long, so 0x1000
in hex.
System address
We have our libc base address, now we have to find the address of the system()
function.
- Framed in red: System address determination.
- Framed in yellow: Little addition.
- Framed in cyan: Check the system address, it looks like it works :)
Final local exploit
At this point, we have everything we need to exploit the binary and get a shell:
Flag
As we can see, we don’t have any return of our function, so I use a little binary called ngrok
to get a netcat on my laptop (without opening ports).
And then, the graal:
Complete exploit code:
|
|