概述
由于C/C++语言本身没有数组越界检查机制,当向缓冲区里写入的数据超过了为其分配的大小时,就会发生缓冲区溢出。
攻击者可以利用缓冲区溢出来窜改进程运行时栈,从而改变程序的正常流向。在分析缓冲区溢出攻击的原理之前,我们先来
复习一下进程在内存中的结构。
进程在内存中的组织形式
Text段主要包含程序代码(一系列可执行的指令),另外还有一些只读的数据。通常操作系统标记该段为只读段,
如果有进程试图修改该段,会引发段错误。
Data段包括已初始化和未初始化的全局变量,静态变量也放于此处。该段的大小是在编译时期计算的。
紧接着Data段的一块内存是由堆和栈共享的区域。堆向下(高地址)增长,栈向上(低地址)增长。
堆中保存动态分配的数据,调用malloc函数或者calloc函数或者使用new操作符会在堆上分配内存。
栈中保存的是函数调用时传递的参数,局部变量的值和一些记录进程运行状态的寄存器的值。
堆和栈所占内存都是在运行期间分配的。如果进程的堆或栈的增长超出了为进程分配的内存大小,
那么该进程会被阻塞,操作系统重新为其分派一块更大的内存。
栈的作用
栈这种数据结构,我们再熟悉不过。它的特点是后进先出(LIFO),在它之上有两个著名的函数,push和pop。
函数是结构化程序设计最重要的技术。程序的执行过程可以看作是连续的函数调用。当一个函数执行完毕时,程序要回到调用
指令的下一条指令(紧接call指令)处继续执行,而栈的特点刚好适合这个条件。
在介绍函数调用的细节之前,我们先来看一下栈帧的概念。
栈帧是栈中的逻辑片段。每个函数调用时,都会push一个栈帧,当函数返回时,pop。
栈帧里面存放着函数的参数,函数局部变量以及为了恢复前一栈帧所需要的数据。
我们知道,栈是实现相关的,不同架构的计算机,栈的增长方向和栈顶指针(ESP)的指向是不一样的。这篇文章里所讲的栈,
都是向低地址增长,栈顶指针是指向栈顶的。 由于ESP的值在程序执行过程中会频繁的改变,用到它的偏移量来定位变量会
很麻烦。因此,编译器使用另外一个寄存器EBP来记录局部基地址。EBP的值对于当前函数来说是不变的。函数局部变量和参数
都可以用到EBP的偏移量来定位。当进入一个新函数执行时,首先把旧的EBP值压栈,然后把当前ESP值作为新的EBP值,接着
改变ESP值来为函数局部变量预留出空间。
函数调用
先看一段代码:
1 void func(int a, int b)
2 {
3 char buffer[5];
4 }
5 int main(void)
6 {
7 func(8, 10);
8 return 0;
9 }
我们把它编译成汇编代码: $ gcc -S function_call.c
可以看到func(8, 10)被译成:
1 movl $10, 4(%esp)
2 movl $8, (%esp)
3 call _func
参数10和8依次压栈,然后执行call指令。call指令会把指令指针寄存器EIP的值压栈,作为函数调用完成后的返回地址ret。
1 _func:
2 pushl %ebp
3 movl %esp, %ebp
4 subl $16, %esp
_func函数先把旧的ebp值压栈,然后把esp的值赋给ebp,作为新的ebp值,最后把esp减去16为局部变量buffer留出空间。
注意虽然buffer只要5个字节,但是由于栈是以16字节边界对齐的,所以实际上分配了16个字节的空间。
func函数被调用时,栈的结构:
好,现在让我们来看一下缓冲区溢出会发生什么?
01 #include <string.h>
02 void func(char *pStr)
03 {
04 char buffer[5];
05 strcpy(buffer, pStr);
06 }
07 int main(void)
08 {
09 char str[32];
10 for (int i = 0; i < 31; ++i)
11 str[i] = 'A';
12 func(str);
13 return 0;
14 }
上面代码存在典型的缓冲区溢出问题。编译,运行,发生了什么?
嗯,弹出一个我们很熟悉的内存访问错误消息框
在上面的代码中,我们向buffer写入一个长字符串,由于strcpy函数没有越界检查,它会一直工作,直到遇见NULL字符。
首先旧的ebp值会被覆盖,接着函数返回地址ret也被改写!甚至连str自身的部分值也被重写了!
'A'的ascii码是0x41,ret的值此时变为0x41414141,这已经不属于该进程的寻址范围内了。
当func函数返回,ret的值送到EIP寄存器,再取指令时便会发生内存访问错误了。
我们发现通过缓冲区溢出的确可以修改函数的返回地址,从而改变程序的正常执行流向。
理论上,我们可以利用这一点来执行任意代码。(未完,待续......)
转载:缓冲区溢出攻击原理、方法及防范(一) - shilcare - 博客园 (cnblogs.com)
最后
以上就是饱满短靴为你收集整理的缓冲区溢出攻击原理、方法及防范(一)的全部内容,希望文章能够帮你解决缓冲区溢出攻击原理、方法及防范(一)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复