While this challenge might look like a heap challenge at first, it’s not…
We can create and delete blog posts, which will be put on the heap, but that’s it for being heap related. The interesting part is hidden in Show the blog owner
This let’s us write a new blog owner, but we’re only allowed to input 7 bytes for this. Let’s check some code to see, what’s behind the blog owner
This will set up a rwx section at a “random” address, but since the random generator is seeded with the current time, we can easily guess the address for this section.
This region will be used to store the blog owner (which is also the one, we can change in Show the blog owner)
So we can write 7 bytes to a rwx section. This already yells to put a shellcode there. But then again 7 bytes aren’t quite much for doing something useful there.
Checking the main function, we can also see, that there’s a hidden menu, when entering 31337, which calls a function, which will for one leak its own address and lets us overwrite the return address with a value smaller then itself. We can use this to return to the rwx section, where we prepared a shellcode, which then will get executed.
Adding blog entries, will create a chunk on the heap and store the address for the blog entry directly behind the blog owner in the rwx section
We can use the blog entries to prepare small ropchains on the heap, and then try to pivot the stack to the heap with our initial “mini” shellcode.
Read the pie leak (because leaks are always good :-))
Prepare stager shellcode in blog owner
Prepare ropchain on heap
Trigger stager shellcode
Let it roll
Quite some stuff that happens there, so, let’s get into detail…
get_pie_leak(True, ADDR, ADDR+0x8)
will set rbp to ADDR+0x8 and set rip to ADDR. Since we created a blog entry, ADDR+0x8 will point to a chunk on the heap
Our stager shellcode
will thus
push the address of the blog entry chunk onto the stack.
pop rsp will pivot the stack to the blog entry. The first pointer of a blog entry is a pointer to its content. Thus we’ll now have the content pointer on top of the stack
pop rbp will now move the content pointer to rbp
leave; ret will thus move rsp to content+8
and this will execute the ropchain we prepared in our blog entry :)
will set rbp to rwx section + 8 and then jump to the read int the leet_leak function
which will now read 24 bytes to the rwx section. So we can put another shellcode there.
Though, we can only use the first 16 bytes for our shellcode, since we have to put another return address at the end, so our ropchain can continue.
But 16 bytes are enough to do a second stager shellcode, which then lets us read the final shellcode.
The nops won’t be in our final shellcode and are only there to let pwntools calculate the jmp next correctly, because the return address will be stored in place of the nops (ADDR).
When the syscall gets executed rsp will point behind the just read data, and we’re writing the next shellcode to rsp.
So, this read will now read 0x246 bytes, to 0x55ace018 and our previous shellcode will then jump there. Should be more than enough to do some proper shellcode.
But there are some blacklisting seccomp rules active
arch : amd64 (so no transfer to 32bit)
open (2)
execve (59)
fork (57)
vfork (58)
clone (56)
No shell possible and we’re also not allowed to open the flag file to read it… But well, there’s still openat syscall to get around this :)
From the other pwnables, we can guess, that the flag will be stored at /home/pwn/flag, so we just do an openat/read/write shellcode to get this thing done.
Like already stated, the previous stager shellcode will read this to the destination, where our jmp is already pointing to, and executes it: