缓冲区溢出漏洞解密详解第一篇
缓冲区溢出漏洞自70年代出现,经Morris蠕虫和Aleph1文章传播。该系列首篇详解本地溢出及利用代码编写,需C语言、汇编、虚拟内存和Unix基础。溢出来源于向数组写入超出容量的数据,覆盖后续重要内容。进程内存分为文本段、数据段和堆栈段,堆栈后进先出且向下增长,EIP寄存器控制指令执行。
缓冲区溢出漏洞,作为一个历史悠久的计算机安全顽疾,早在1970年代就已存在。直到1980年代,Morris蠕虫事件才让这一漏洞首次大规模暴露在公众视野中。进入1990年代,Aleph1的经典文章《Smashing the Stack for Fun and Profit》及其配套攻击代码开始在互联网上广泛传播,从此,缓冲区溢出的“潘多拉魔盒”被彻底打开,成为黑客攻击与安全防御的核心战场。
本文作为系列文章的开篇,将深入剖析本地溢出这一最基础的漏洞类型,并手把手指导读者编写利用代码。我们的目标是讲透原理,让读者真正理解漏洞背后的机制,而不仅仅是复制粘贴攻击代码。
为了顺利跟上后续内容,你需要具备一定的C语言和汇编基础,同时了解虚拟内存、进程的内存布局方式,以及setuid二进制文件的基本概念。当然,你还需要熟练使用UNIX系统,最好具备gdb/cc调试与编译的经验。本系列主要针对Linux/ix86环境展开,不同操作系统或架构的细节会存在差异。在后续文章中,我们将逐步介绍更高级的溢出技术和shellcode编写技巧。
什么是溢出?
如果你写过C语言,一定对字符数组不陌生。数组中的元素类型相同,比如int、char、float。与其他数据结构类似,数组也分为“静态”和“动态”两类。静态变量存放在程序的数据段,而动态变量则在程序运行时的堆栈段中分配和释放。“基于堆栈”的溢出正是发生在堆栈段——当我们向数据结构中写入超过其容量的数据时,例如向一个只能存储12字节的数组强行塞入20字节,超出界限的数据就会覆盖掉后续的重要数据。简单来说,溢出就是这么一回事。
一个Linux ELF格式的可执行文件,其内存布局相当复杂。尤其是在ELF(可执行与可链接格式,详情可搜索“Executable and Linkable Format”)和共享库引入之后,结构变得更加复杂。但无论如何,每个进程在运行时都包含三个基本段:
1. 文本段(Text Segment):只读区域,存放所有程序指令。例如下面这段C代码对应的指令就会存放在这里。
2. 数据段(Data Segment):存放已初始化和未初始化的数据(也称为BSS段)。例如:
如果你写 int i; ,这个变量是未初始化的,会被放到数据段的“未初始化变量”部分(BSS)。
如果你写 int j = 5; ,这个变量是已初始化的,空间就会分配在数据段的“已初始化变量”部分。
3. 堆栈段(Stack Segment):动态变量(C语言中称为自动变量)在这里分配和释放,同时用于临时存储函数返回地址。例如下面的函数中,变量 i 就是在堆栈上产生的,函数返回后它就被销毁了。
如果用符号表示堆栈的内存布局,大致如下:
0xBFFFFFFF ---------------------
| |
| . |
| . |
| . |
| . |
| etc |
| env/argv pointer. |
| argc |
|-------------------|
| |
| stack |
| |
| | |
| | |
| V |
/ /
\ \
| |
| ^ |
| | |
| | |
| |
| heap |
|-------------------|
| bss |
|-------------------|
| initialized data |
|-------------------|
| text |
|-------------------|
| shared libraries |
| etc. |
0x8000000 |-------------------|
堆栈(Stack)
从数据结构课程中我们知道,堆栈是一种后进先出(LIFO)的数据结构。CPU通过PUSH和POP等特殊指令直接控制堆栈。你压入一些数据,再弹出一些数据。后进入的数据先被弹出。专业地说,第一个被弹出堆栈的,是最后一个被压入的数据。
CPU中的SP寄存器(堆栈指针)保存着即将从堆栈中弹出的数据的地址。至于SP是指向最后的数据,还是指向最后数据后面的地址,这取决于具体的CPU架构。在ix86架构下,SP指向的是堆栈中最后数据的地址。在ix86保护模式(32位/双字)下,PUSH和POP指令按4字节单元操作。另一个重要细节:堆栈是向下增长的。也就是说,如果SP当前为0xFF,执行PUSH EAX之后,SP会变成0xFC,而EAX的值会被存放到0xFC这个地址中。
更具体地说,PUSH指令会从ESP(对照上图)减去4个字节,然后将一个双字压入堆栈,放到ESP寄存器所指的地址。POP指令则读取ESP寄存器中的地址,弹出该地址指向的值,然后ESP加4。假设ESP初始化为0x1000,我们来看一段汇编代码的执行过程:
PUSH dword1 ; dword1的值是1,执行后ESP = 0xFFC (0x1000 - 4) PUSH dword2 ; dword2的值是2,执行后ESP = 0xFF8 (0xFFC - 4) PUSH dword3 ; dword3的值是3,执行后ESP = 0xFF4 (0xFF8 - 4) POP EAX ; EAX = 3,执行后ESP = 0xFF8 (0xFF4 + 4) POP EBX ; EBX = 2,执行后ESP = 0xFFC (0xFF8 + 4) POP ECX ; ECX = 1,执行后ESP = 0x1000 (0xFFC + 4)
堆栈除了用作动态变量的临时存储,还用于保存函数调用时的临时变量地址,以及在函数之间传递参数。当然,这也是漏洞滋生的温床。
EIP寄存器,CALL和RET指令
在每个机器周期中,CPU都会查询指令指针寄存器(在ix86 32位保护模式下称为EIP——扩展指令指针)中保存的内容,以确定下一步要执行什么指令。EIP中存放的是下一条将要执行的指令的地址。通常情况下,地址是连续的——下一条指令在内存中比当前指令靠后几个字节。CPU会根据当前指令的长度计算出“靠后的字节数”,然后加到当前地址上。举例来说:假设当前指令地址是0x8048438,这个值就写在EIP中。CPU执行地址0x8048438处的指令,比如是一条PUSH指令。CPU知道这条PUSH指令是1字节长的,所以下一条指令就在0x8048439,可能是MOV指令。执行完PUSH后,CPU就会把MOV指令的地址放到EIP中。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
零基础Python网络安全学习指南,包住宿实战培训
先抛出几个核心判断:网络安全人才缺口确实已经超过70万。这个数字不算夸张,各大招聘网站上安全岗位的薪资涨幅和需求增长都是实实在在的。但实话实说,行业真正缺的是能上手干活的人,不是只懂几个理论概念的新手。因此,一套扎实且成体系的训练方案,对于零基础转行或进阶提升就显得格外关键。 从零基础到能够独立应对
网络安全定义与核心概念详解
谈到网络安全,不同组织与标准体系对其定义虽有差异,但核心目标高度统一:保护信息与系统不受威胁侵害。以下梳理几种主流定义—— 什么是网络安全? 国际标准化组织(ISO)在ISO-74982文献中将安全定义为:最大程度地降低数据和资源遭受攻击的可能性。该定义虽简短,却精准点出安全的本质——即风险控制。
IIS 7.0网站漏洞利用与修复方法指南
先来聊聊当前网络安全领域比较流行的一种实战技巧——以PHP环境为例,详细讲解图片马合并与解析漏洞利用的具体操作步骤。整个过程并不复杂,但细节往往决定成败,大家跟着流程逐步操作即可。 合并一张PHP一句话图片马 首先,我们需要将一句话木马脚本与一张正常图片合并,生成一个看似无害的图片文件。合并方式主要
织梦管理系统后台查找功能教程
通过SQL注入漏洞获取织梦CMS(DedeCMS)管理员密码后,满怀期待地准备进入后台,却发现怎么也找不到登录入口——这种情况其实相当常见。别着急,这里有一个实用的技巧值得尝试。 直接在网站地址后面添加以下路径: include dialog select_media php?f=form1 mur
微软IE浏览器BrowseDialog类(ccrpbds6.dll)拒绝服务安全漏洞深度分析
BrowseDialog Class (ccrpbds6 dll) 导致 Internet Explorer 拒绝服务漏洞分析 该漏洞的PoC(概念验证代码)实现极为直接——触发浏览器崩溃的条件简单得令人意外。测试环境采用Windows XP Professional SP2(已安装全部补丁)并运行
- 热门数据榜
相关攻略
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:10
2026-07-25 22:10
2026-07-25 22:10
2026-07-25 22:10
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

