手把手教你栈溢出从入门到放弃.pdf

  1. 1、本文档共27页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
手把手教你栈溢出从入门到放弃

手把手教你栈溢出从入门到放弃 6 days ago 二进制安全 admin 本文来源:长亭技术专栏 作者:Jwizard 0x00 写在最前面 开场白:快报快报!今天是 2017 Pwn2Own 黑客大赛的第一天,长亭安全研究实 验室在比赛中攻破 Linux 操作系统和 Safari 浏览器(突破沙箱且拿到系统最高 权限),积分 14 分,在 11 支队伍中暂居 Master of Pwn 第一名。作为热爱技 术乐于分享的技术团队,我们开办了这个专栏,传播普及计算机安全的 “黑魔 法”,也会不时披露长亭安全实验室的最新研究成果。 安全领域博大精深,很多童鞋都感兴趣却苦于难以入门,不要紧,我们会从最 基础的内容开始,循序渐进地讲给大家。技术长路漫漫,我们携手一起出发 吧。 0x10 本期简介 在计算机安全领域,缓冲区溢出是个古老而经典的话题。众所周知,计算机程 序的运行依赖于函数调用栈。栈溢出是指在栈内写入超出长度限制的数据,从 而破坏程序运行甚至获得系统控制权的攻击手段。本文将以 32 位 x86 架构下的 程序为例讲解栈溢出的技术详情。 为了实现栈溢出,要满足两个条件。第一,程序要有向栈内写入数据的行为; 第二,程序并不限制写入数据的长度。历史上第一例被广泛注意的 “莫里斯蠕 虫”病毒就是利用 C 语言标准库的 gets() 函数并未限制输入数据长度的漏 洞,从而实现了栈溢出。 Fig 1. 波士顿科学博物馆保存的存有莫里斯蠕虫源代码的磁盘 (source: Wikipedia) 如果想用栈溢出来执行攻击指令,就要在溢出数据内包含攻击指令的内容或地 址,并且要将程序控制权交给该指令。攻击指令可以是自定义的指令片段,也 可以利用系统内已有的函数及指令。 0x20 背景知识 在介绍如何实现溢出攻击之前,让我们先简单温习一下函数调用栈的相关知 识。 函数调用栈是指程序运行时内存一段连续的区域,用来保存函数运行时的状态 信息,包括函数参数与局部变量等。称之为 “栈”是因为发生函数调用时,调 用函数(caller)的状态被保存在栈内,被调用函数(callee)的状态被压入 调用栈的栈顶;在函数调用结束时,栈顶的函数(callee)状态被弹出,栈顶 恢复到调用函数(caller)的状态。函数调用栈在内存中从高地址向低地址生 长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。 Fig 2. 函数调用发生和结束时调用栈的变化 函数状态主要涉及三个寄存器--esp,ebp,eip。esp 用来存储函数调用栈的 栈顶地址,在压栈和退栈时发生变化。ebp 用来存储当前函数状态的基地址, 在函数运行时不变,可以用来索引确定函数参数或局部变量的位置。eip 用来 存储即将执行的程序指令的地址,cpu 依照 eip 的存储内容读取指令并执行, eip 随之指向相邻的下一条指令,如此反复,程序就得以连续执行指令。 下面让我们来看看发生函数调用时,栈顶函数状态以及上述寄存器的变化。变 化的核心任务是将调用函数(caller)的状态保存起来,同时创建被调用函数 (callee)的状态。 首先将被调用函数(callee)的参数按照逆序依次压入栈内。如果被调用函数 (callee)不需要参数,则没有这一步骤。这些参数仍会保存在调用函数 (caller)的函数状态内,之后压入栈内的数据都会作为被调用函数 (callee)的函数状态来保存。 Fig 3. 将被调用函数的参数压入栈内 然后将调用函数(caller)进行调用之后的下一条指令地址作为返回地址压入 栈内。这样调用函数(caller)的 eip (指令)信息得以保存。 Fig 4. 将被调用函数的返回地址压入栈内 再将当前的 ebp 寄存器的值(也就是调用函数的基地址)压入栈内,并将 ebp 寄存器的值更新为当前栈顶的地址。这样调用函数(caller)的 ebp (基地 址)信息得以保存。同时,ebp 被更新为被调用函数(callee)的基地址。 Fig 5. 将调用函数的基地址(ebp)压入栈内,并将当前栈顶地址传到 ebp 寄 存器内 再之后是将被调用函数(callee)的局部变量等数据压入栈内。 Fig 6. 将被调用函数的局部变量压入栈内 在压栈的过程中,esp 寄存器的值不断减小(对应于栈从内存高地址向低地址 生长)。压入栈内的数据包括调用参数、返回地址、调用函数的基地址,以及 局部变量,其中调用参数以外的数据共同构成了被调用函数(callee)的状 态。在发生调用时,程序还会将被调用函数(callee)的指令地址存到 eip 寄 存器内,这样

文档评论(0)

jiupshaieuk12 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

版权声明书
用户编号:6212135231000003

1亿VIP精品文档

相关文档