缓冲区溢出攻击原理、方法及防范(一)

由于C/C++语言本身没有数组越界检查机制,当向缓冲区里写入的数据超过了为其分配的大小时,就会发生缓冲区溢出。

攻击者可以利用缓冲区溢出来窜改进程运行时栈,从而改变程序的正常流向。在分析缓冲区溢出攻击的原理之前,我们先来

复习一下进程在内存中的结构。

进程在内存中的组织形式

缓冲区溢出攻击原理、方法及防范(一)

Text段主要包含程序代码(一系列可执行的指令),另外还有一些只读的数据。通常操作系统标记该段为只读段,

如果有进程试图修改该段,会引发段错误。

Data段包括已初始化和未初始化的全局变量,静态变量也放于此处。该段的大小是在编译时期计算的。

紧接着Data段的一块内存是由堆和栈共享的区域。堆向下(高地址)增长,栈向上(低地址)增长。

堆中保存动态分配的数据,调用malloc函数或者calloc函数或者使用new操作符会在堆上分配内存。

栈中保存的是函数调用时传递的参数,局部变量的值和一些记录进程运行状态的寄存器的值。

堆和栈所占内存都是在运行期间分配的。如果进程的堆或栈的增长超出了为进程分配的内存大小,

那么该进程会被阻塞,操作系统重新为其分派一块更大的内存。

栈的作用

栈这种数据结构,我们再熟悉不过。它的特点是后进先出(LIFO),在它之上有两个著名的函数,push和pop。

函数是结构化程序设计最重要的技术。程序的执行过程可以看作是连续的函数调用。当一个函数执行完毕时,程序要回到调用

指令的下一条指令(紧接call指令)处继续执行,而栈的特点刚好适合这个条件。

在介绍函数调用的细节之前,我们先来看一下栈帧的概念。

栈帧是栈中的逻辑片段。每个函数调用时,都会push一个栈帧,当函数返回时,pop。

栈帧里面存放着函数的参数,函数局部变量以及为了恢复前一栈帧所需要的数据。

我们知道,栈是实现相关的,不同架构的计算机,栈的增长方向和栈顶指针(ESP)的指向是不一样的。这篇文章里所讲的栈,

都是向低地址增长,栈顶指针是指向栈顶的。 由于ESP的值在程序执行过程中会频繁的改变,用到它的偏移量来定位变量会

很麻烦。因此,编译器使用另外一个寄存器EBP来记录局部基地址。EBP的值对于当前函数来说是不变的。函数局部变量和参数

都可以用到EBP的偏移量来定位。当进入一个新函数执行时,首先把旧的EBP值压栈,然后把当前ESP值作为新的EBP值,接着

改变ESP值来为函数局部变量预留出空间。

函数调用

先看一段代码:
1voidfunc(inta,intb)

2{

3charbuffer[5];

4}

5intmain(void)

6{

7func(8,10);

8return0;

9}
我们把它编译成汇编代码: $ gcc -S function_call.c

可以看到func(8, 10)被译成:
1movl$10,4(%esp)

2movl$8,(%esp)

3call_func
参数10和8依次压栈,然后执行call指令。call指令会把指令指针寄存器EIP的值压栈,作为函数调用完成后的返回地址ret。
1_func:

2pushl%ebp

3movl%esp,%ebp

4subl$16,%esp
_func函数先把旧的ebp值压栈,然后把esp的值赋给ebp,作为新的ebp值,最后把esp减去16为局部变量buffer留出空间。

注意虽然buffer只要5个字节,但是由于栈是以16字节边界对齐的,所以实际上分配了16个字节的空间。

func函数被调用时,栈的结构:

缓冲区溢出攻击原理、方法及防范(一)

好,现在让我们来看一下缓冲区溢出会发生什么?
01#include

02voidfunc(char*pStr)

03{

04charbuffer[5];

05strcpy(buffer,pStr);

06}

07intmain(void)

08{

09charstr[32];

10for(inti=0;i<31;++i)

11str[i]='A';

12func(str);

13return0;

14}
上面代码存在典型的缓冲区溢出问题。编译,运行,发生了什么?

嗯,弹出一个我们很熟悉的内存访问错误消息框

缓冲区溢出攻击原理、方法及防范(一)

在上面的代码中,我们向buffer写入一个长字符串,由于strcpy函数没有越界检查,它会一直工作,直到遇见NULL字符。

首先旧的ebp值会被覆盖,接着函数返回地址ret也被改写!甚至连str自身的部分值也被重写了!

'A'的ascii码是0x41,ret的值此时变为0x41414141,这已经不属于该进程的寻址范围内了。

当func函数返回,ret的值送到EIP寄存器,再取指令时便会发生内存访问错误了。

我们发现通过缓冲区溢出的确可以修改函数的返回地址,从而改变程序的正常执行流向。

理论上,我们可以利用这一点来执行任意代码。(未完,待续......)
原文链接: https://www.cnblogs.com/shilcare/archive/2010/12/23/1912987.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/19188

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 下午8:11
下一篇 2023年2月7日 下午8:11

相关推荐