首页
社区
课程
招聘
[原创]缓冲区溢出技术分析:栈溢出攻击
2021-2-26 15:12 6926

[原创]缓冲区溢出技术分析:栈溢出攻击

2021-2-26 15:12
6926

缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动。缓冲区溢出是一种普遍且危险的漏洞,存在于软件中,以及更底层的操作系统中。利用缓冲区溢出攻击,可以导致程序运行失败、系统故障,甚至被他人控制主机等后果。本文简单讲解缓冲区溢出的原理,并举出实例进行分析。

01 溢出原理

图片描述

 

图 1 内存示意图

 

缓冲区可以理解为一段可读写的内存区域。代码段存放的是程序的机器码和只读数据。数据段存储的是静态数据和用户的全局变量。堆存储程序运行时分配的变量,大小不固定,由内存地址低向高增长。栈存放函数调用时的临时信息结构,由内存地址高向低增长。入栈(PUSH)时,栈顶变小。出栈(POP)时,栈顶变大。

 

除了代码段和数据区域,其他的内存区域都能作为缓冲区,因此缓冲区溢出的位置可能在数据段、也可能在堆栈段。
图片描述

 

图 2 栈示意图

 

寄存器
ESP(栈指针寄存器)是指针寄存器的一种,用于存放函数栈顶指针,指向栈的栈顶。

 

EBP(基址指针寄存器)是指针寄存器的一种,用于存放函数栈底指针,指向当前活动记录的底部。

 

栈溢出漏洞产生的主要原因是在函数调用时,将函数的返回地址保存入栈,即调用函数运行完毕后将要返回的主函数的地址会先被入栈,如果修改了这个返回地址,并且使这个返回地址指向一个新的内存地址,那么程序就能从其他地址继续执行,这样就产生了栈溢出漏洞攻击。

 

比如下面这个例子:

1
2
3
4
5
void fun(unsigned char *data)
{
    unsigned char buffer[BUF_LEN];
    strcpy((char*)buffer,(char*)data);//溢出点
}

这个函数是一个典型的栈溢出代码,在使用不安全的strcpy库函数的时候,系统会将data的全部数据拷贝到缓冲区详细设计的区域。因为缓冲区的长度是有限的,当data的数据长度超过了BUF_LEN的时候,便会产生缓冲区溢出。

02 准备环境

Windows XP
IDA
OD
以及两个C程序

03 实例分析

第一个符合缓冲区C程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "stdio.h"
#include "string.h"
 
char test[]="abcdefg";
 
int main()
{
 char buffer[8];
 strcpy(buffer,test);
 printf("%s\n",buffer);
 getchar ();
 return 0;
}

第二个缓冲区溢出C程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "stdio.h"
#include "string.h"
 
char test[]="abcdefghijklmn";
 
int main()
{
 char buffer[8];
 strcpy(buffer,test);
 printf("%s\n",buffer);
 getchar ();
 return 0;
}

在编译,建立完成程序后,运行第一个程序,按回车能正确关闭:
图片描述

 

图片描述

 

运行第二个程序,按回车则会出现内存报错:

 

图片描述

 

图片描述

 

接下来用OD和IDA打开第一个程序:
图片描述

 

在IDA中看到入口地址为401010,再用OD打开,将地址跳转到401010,并下断点。
图片描述

 

然后再IDA中交叉应用查找(crtl+x),找到call main函数的地址为401694。
图片描述

 

在OD中找到这个内存地址,并下断点,然后按F9执行至断点位置。
图片描述

 

在401694call函数的下个地址401699为call完main函数后的返回地址。

 

call指令分为2步,第一步,先将call指令下的地址入栈,作为返回地址记录,第二步,跳转到call的地址。在OD的栈结构中可以看到,当call之前,0012F88的栈数据为00000001。

 

图片描述
当步入call中后,地址401699已经入栈。
图片描述

 

当运行到sub esp,4c的时候查看栈空间:

 

图片描述

 

其中,12FF84存储的是main函数的返回地址,12FF80存储的是父函数的EBP。
图片描述

 

继续按F8单步执行到strcpy函数调用处:

 

图片描述

 

调用strcpy的时候先将test参数入栈,然后入栈buffer参数,调用strcpy函数之后将12FF78处的0xCC(烫烫烫烫烫烫烫)修改为abcdefg。按F8执行之后查看栈空间。

 

此处为调用的abcdefg:

 

图片描述
此处为将内存12FF78处开始载入abcdefg,载入完成后如图:

 

图片描述
接下来查看第二个程序:

 

用OD打开第二个程序,断点位置如上,前边重复如上操作,直到执行到查看栈,可看到Main函数返回地址依旧在12FF84处。
图片描述

 

接下来查看第二个程序:

 

用OD打开第二个程序,断点位置如上,前边重复如上操作,直到执行到查看栈,可看到Main函数返回地址依旧在12FF84处。
图片描述

 

接着运行,可看到在strcpy函数调用test时,12FF84处的栈任还指向返回地址
图片描述

 

但在载入buffer缓冲区时,因缓冲区数据过大,已经将返回地址占据,使main主程序无法正常返回。

 

图片描述

 

所以在执行完后返回地址错误,所以内存报错

 

此上栈溢出实例分析完毕。

利用:

当输入“abcdefghijklmn”时,“mn”会将返回main函数的返回地址覆盖,那么这里就可以利用,将“abcdefghijklmn”改为“abcdefghijklXXXX”,这样“XXXX”则为新的返回地址。当弹出返回地址的时候,ESP指针会自增4,指向main函数的三个参数,那么可以利用这一特性,将返回地址覆盖为“jmp esp”指令的地址,然后将main函数的参数覆盖为shellcode,这样当执行完main函数return的时候就会跳转到jmp esp指令处然后执行esp中的代码。当test数组为“abcdefghijklXXXX..shellcode”的时候,XXXX为返回地址,接着的是shellcode,然后就可以通过shellcode达成某些目的。


阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回