缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动。缓冲区溢出是一种普遍且危险的漏洞,存在于软件中,以及更底层的操作系统中。利用缓冲区溢出攻击,可以导致程序运行失败、系统故障,甚至被他人控制主机等后果。本文简单讲解缓冲区溢出的原理,并举出实例进行分析。
01 溢出原理
图 1 内存示意图
缓冲区可以理解为一段可读写的内存区域。代码段存放的是程序的机器码和只读数据。数据段存储的是静态数据和用户的全局变量。堆存储程序运行时分配的变量,大小不固定,由内存地址低向高增长。栈存放函数调用时的临时信息结构,由内存地址高向低增长。入栈(PUSH)时,栈顶变小。出栈(POP)时,栈顶变大。
除了代码段和数据区域,其他的内存区域都能作为缓冲区,因此缓冲区溢出的位置可能在数据段、也可能在堆栈段。
图 2 栈示意图
寄存器
ESP(栈指针寄存器)是指针寄存器的一种,用于存放函数栈顶指针,指向栈的栈顶。
EBP(基址指针寄存器)是指针寄存器的一种,用于存放函数栈底指针,指向当前活动记录的底部。
栈溢出漏洞产生的主要原因是在函数调用时,将函数的返回地址保存入栈,即调用函数运行完毕后将要返回的主函数的地址会先被入栈,如果修改了这个返回地址,并且使这个返回地址指向一个新的内存地址,那么程序就能从其他地址继续执行,这样就产生了栈溢出漏洞攻击。
比如下面这个例子:
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程序:
#include "stdio.h" #include "string.h" char test[]="abcdefg"; int main() { char buffer[8]; strcpy(buffer,test); printf("%s",buffer); getchar (); return 0; }
第二个缓冲区溢出C程序:
#include "stdio.h" #include "string.h" char test[]="abcdefghijklmn"; int main() { char buffer[8]; strcpy(buffer,test); printf("%s",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达成某些目的。
来源:freebuf.com 2021-02-26 15:01:24 by: 华云安huaun
请登录后发表评论
注册