缓冲区溢出攻击原理及ShellCode的构造
2017-04-26张华
张华
摘要:缓冲区溢出是一种常见的网络安全漏洞,可以对计算机操作系统,应用软件造成巨大的威胁。通过缓冲区溢出攻击,网络黑客可以远程执行恶意代码,甚至获得主机的控制权,从而开始各种非法操作。该文分析了缓冲区溢出漏洞的产生原因及其原理,结合具体代码介绍了ShellCode的构造方法。
关键词:缓冲区溢出;网络安全;漏洞;ShellCode
中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2017)06-0085-02
Abstract: Buffer overflow is a common network security vulnerability, which can pose a great threat to computer operating system and application software. Through buffer overflow attacks, network hackers can execute malicious code remotely , or even get the control of the host to carry out a variety of illegal operations. This paper analyzes the causes and principles of buffer overflow vulnerability, introduces the construction method of ShellCode with the specific code.
Key words: buffer overflow; network security; vulnerability; ShellCode
1 概述
缓冲区溢出攻击并非一种新的攻击手段。早在1989年,Spafford就做了一個关于缓冲区溢出程序的分析报告。2003年的“冲击波”病毒,2004年的“震荡波”病毒就是利用了缓冲区溢出的漏洞。然而时至今日,我们仍然时时刻刻感受着来自缓冲区溢出漏洞的威胁。图1所示的是中国国家信息安全漏洞库在2017年2月份下旬收录的缓冲区溢出漏洞。不到十天时间,现有的计算机系统就出现如此多的缓冲区溢出漏洞。依据CNVD(中国信息安全漏洞共享平台)的统计数据,缓冲区溢出类型的漏洞在各种类型的漏洞比例中,仍然名列前茅。因此深入学习探讨缓冲区溢出漏洞是很有必要的。
缓冲区溢出漏洞原因可以分为栈溢出、堆溢出、文件流溢出、格式化字符串溢出。本文主要介绍栈溢出漏洞的原因、原理,实施该攻击手段的一个核心步骤-ShellCode的编写。
2 漏洞原因和原理
2.1 产生原因
堆栈溢出漏洞是通过在程序的堆栈里写入超过其长度的内容,造成堆栈溢出,从而使得程序的堆栈遭到破坏。例如下列程序:
这段程序中buffer数组只能存放8个字符,而strcpy()把一个长度超过8的字符串复制到buffer数组中,就会造成缓冲区buffer的溢出。类似这样的函数还有strcat(),sprintf(),gets(),scanf(),getchar()等。这些函数都没有边界检查,因此为缓冲区溢出攻击提供了基础条件。如果开发人员没有检查参数的长度就直接复制到缓冲区中去,这个软件产品就存在着缓冲区溢出的漏洞,为别有用心的攻击者创造了有利的条件。
2.2 原理
要深入理解缓冲区溢出的原理,我们得先从Windows函数执行原理说起。调用一个函数时,计算机需要执行如下步骤:
1)函数的各个参数(假设有3个参数,分别是param1,param2,param3)从右到左依次入栈;
2)指令寄存器(EIP)的内容作为返回地址入栈;
3)基址寄存器(EBP)的内容入栈;
4)把当前的ESP的内容赋值给EBP,作为新的基地址;
5)为函数的局部变量分配空间,假设先后有两个int类型的变量var1,var2,则var1,var2变量的地址分别为[EBP-4],[EBP-8];
函数执行完毕时,根据堆栈原理,出栈顺序为:局部变量var2,var1,基址寄存器(EBP)的内容,指令寄存器(EIP)的内容,param1,param2,param3。
根据本文2.1的程序,局部变量buffer数组8个元素的从低到高地址分别为[EBP-32],[EBP-28],…,[EBP-4]。函数strcpy()把字符串复制到buffer数组时,数组元素操作顺序为从低地址向高地址,如果字符串长度超过8个字符,超过部分的字符串就会覆盖了EBP,RET返回地址,从而造成缓冲区溢出。通过构造特殊的字符串,使其覆盖RET返回地址,从而让程序执行特定程序(ShellCode),这就是堆栈溢出攻击。
3 构造ShellCode
ShellCode实际上是用机器语言编写的一段程序,当计算机出现缓冲区溢出时转而去执行的代码。攻击者可以通过ShellCode获得主机的系统特权,从而进行非法操作。ShellCode的编写是缓冲区溢出攻击最关键的步骤。
本文以打开远程主机DOS窗口为例。在VC++6.0中,通过图3所示这段程序就可以完成此功能。
从汇编(机器)语言的角度来说,上述代码最关键的是LoadLibrary("msvCRT.dll"),以及System("command.com")这两个函数调用。要调用一个函数,需要知道这个函数的内存地址,并获得函数参数。对于函数内存地址问题,我们可以在VC++6.0中按F10进入调试模式,点击调试工具栏的“Disassembly”按钮,在反编译模式中开启“Code Bytes”选项。笔者在32位windows7操作系统调试,得到LoadLibrary(),System()函数的地址分别为0x7689DE15,0x77B1C976。而函数参数问题,我们可以逐个字符地将参数字符串入栈,最后再通过汇编指令push esp完成参数字符串偏移地址入栈操作。调用System("command.com")函数的汇编代码如图4所示,LoadLibrary("msvCRT.dll")可参考此代码编写。
将上述汇编语言程序在VC++6.0中转成机器语言形式,即为通过缓冲区溢出漏洞远程启动主机DOS窗口的ShellCode,如图5所示。
4 结论
本文详细分析了缓冲区溢出漏洞的原因及原理,并以远程启动主机的DOS窗口为例,指出ShellCode构建方法。由于缓冲区溢出漏洞与软件开发过程中的软件设计、编码规范、软件测试息息相关,因此这种漏洞难以彻底解决,将一直是计算机系统安全的重要威胁。因此该问题的研究工作仍然具有实际意义。
参考文献:
[1] 中国信息安全漏洞共享平台.漏洞信息月度通报2016(12)[EB/OL].http://www.cnvd.org.cn/webinfo/show/4026.
[2] 刘绍翰,许建真,张福炎.基于缓冲溢出漏洞的攻击及其预防研究综述[J].计算机应用与软件,2004,21(1):83-86.
[3] 闳刘鑫,张永涛,李鸥.Windows系统下缓存区溢出攻击实现与防范[J].微计算机信息,2005(26): 3-12.
[4] 石志国,薛为民,江俐.计算机网络安全教程[M].北京:清华大学出版社,北京交通大学出版社,2004.
[5] 沈美明,温冬婵.IBM—PC汇编语言程序设计[M].北京:清华大学出版社,1998.
[6] 鲁珂,赵继东.计算机信息系统安全实验教程[M].成都:电子科技大学出版社,2007