栈溢出篇1

1.定义:

​ 栈溢出是缓冲区溢出的一种,当缓冲区数据大于缓冲区大小时,缓冲区以外的有用数据就会被多出来的缓冲区数据覆盖改写,从而可能导致程序崩溃

1
2
3
4
5
缓冲区:程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区

--栈溢出(Stack overflow)
--堆溢出(Heap overflow)
--Data段溢出(比如bss段,比较少见)

2.原理:

​ 栈溢出漏洞在ctf题中常被用来覆盖程序的返回地址,以达到某函数返回(return)时,不再是返回原先的返回函数地址,而是返回到我们为其指定地址的地方。

举个栗子,解释覆盖数据原理:

C源码test.c

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
void Print() //Pirnt函数地址将作为我们修改后的返回地址
{|
puts("Hello Pwn!");
}
int main()
{
char buff[10];
gets(buff); //利用gets函数漏洞
return 0;
}

接下来,我们使用gcc -fno-stack-protector -no-pie -o test test.c

1
2
-fno-stack-protector:禁用栈保护(no canary),防止程序检测栈溢出
-no-pie:去掉地址随机化,不然每次程序运行函数地址都会发生改变,我们第一次找到Print函数的地址写入exp,执行exp,Print函数地址改变,之前写入的Print函数地址就无效了

9b2bee5574c148d28fbe7f4496ee165f

以上为我们在输入端输入“AAAAAAAAAAAAAAAAAA”+Print地址(需构造exp)时栈的变换情况rbp为计算机寄存器,它表示栈底指针的地址)

由上可知,gets函数可以无限的接收字符串(直至接受到换行符或EOF时才停止),即使数据超过我们分配的10字节空间,它也无法检测到,因此我们可以通过覆盖函数的返回地址来使函数跳转到任意我们想要跳到的地方