协程4 --- 一个特殊的栈溢出例子

文章目录

  • 代码
  • 运行结果
  • 分析

代码

先看下面这个程序流程:

有个长度位24的字符数组buffer,前面16个字符初始化。
attack函数的地址复制到后面8个字符(编译成64位程序,指针大小为8Byte)。
打印信息:do Something
调用doSomething,函数内调用了copy函数拷贝到temp变量中,但是注意temp变量长度只有16。
打印信息:do next

提问:do next会打印出来吗

#include <stdio.h>
#include <stdlib.h>

#define BUFFER_LEN 24

void attack()
{
    printf("Hello. I will close your program.\n");
    exit(1);
}

void copy(char* src, char* dest, int n)
{
    for (int i = 0; i < n; ++i)
    {
        dest[i] = src[i];
    }
}

void doSomething(char* str, int n)
{
    // 字符串拷贝
    char temp[16];
    copy(str, temp, n);
}

int main()
{
    char buffer[BUFFER_LEN] =
    {
        'w', 'o', 'l', 'd',
        'a', 'b', 'a', 'b', 'a', 'b',
        'a', 'b', 'a', 'b', 'a', 'b'
    };

    // 将函数注册到字符串最后八个字节
    int n = BUFFER_LEN - 8;
    for (int i = 0; i < 8; ++i)
    {
        buffer[n+i] = (char)((((long)(&attack)) >> (i*8)) & 0xff);
    }

    printf("do Something\n");
    // 运行程序
    doSomething(buffer, BUFFER_LEN);
    // 继续往下执行
    printf("do next\n");

    return 0;
}

运行结果

注意这边用了-O1优化,-fno-stack-protector禁用堆栈保护。
在这里插入图片描述

分析

分析之前先普及一下几点知识

三个寄存器:
rip指向要运行的代码
rbp指向栈底
rsp指向栈顶

程序运行时候的内存分布(当然这个大概是Linux 0.11的,现在的不长这样,不过大体是类似的):
在这里插入图片描述

这边注意一下栈是往下生长的

objdump -d stackattack 看一下汇编

gcc -O1 -o stackattack stackattack.c -g -fno-stack-protector
objdump -d stackattack

000000000040117f <main>:
  40117f:       48 83 ec 28             sub    $0x28,%rsp // 栈中开辟临时变量空间
  401183:       48 c7 44 24 10 00 00    movq   $0x0,0x10(%rsp)
  40118a:       00 00 
  40118c:       c6 04 24 77             movb   $0x77,(%rsp)
  401190:       c6 44 24 01 6f          movb   $0x6f,0x1(%rsp)
  401195:       c6 44 24 02 6c          movb   $0x6c,0x2(%rsp)
  40119a:       c6 44 24 03 64          movb   $0x64,0x3(%rsp)
  40119f:       c6 44 24 04 61          movb   $0x61,0x4(%rsp)
  4011a4:       c6 44 24 05 62          movb   $0x62,0x5(%rsp)
  4011a9:       c6 44 24 06 61          movb   $0x61,0x6(%rsp)
  4011ae:       c6 44 24 07 62          movb   $0x62,0x7(%rsp)
  4011b3:       c6 44 24 08 61          movb   $0x61,0x8(%rsp)
  4011b8:       c6 44 24 09 62          movb   $0x62,0x9(%rsp)
  4011bd:       c6 44 24 0a 61          movb   $0x61,0xa(%rsp)
  4011c2:       c6 44 24 0b 62          movb   $0x62,0xb(%rsp)
  4011c7:       c6 44 24 0c 61          movb   $0x61,0xc(%rsp)
  4011cc:       c6 44 24 0d 62          movb   $0x62,0xd(%rsp)
  4011d1:       c6 44 24 0e 61          movb   $0x61,0xe(%rsp)
  4011d6:       c6 44 24 0f 62          movb   $0x62,0xf(%rsp) // 赋值

  4011db:       b8 00 00 00 00          mov    $0x0,%eax
  4011e0:       be 32 11 40 00          mov    $0x401132,%esi // attack函数地址
  4011e5:       8d 0c c5 00 00 00 00    lea    0x0(,%rax,8),%ecx // i*8
  4011ec:       48 89 f2                mov    %rsi,%rdx
  4011ef:       48 d3 fa                sar    %cl,%rdx // 算数右移
  4011f2:       88 54 04 10             mov    %dl,0x10(%rsp,%rax,1) // dl就是rdx & 0xff 写入目标字符串
  4011f6:       48 83 c0 01             add    $0x1,%rax // ++i
  4011fa:       48 83 f8 08             cmp    $0x8,%rax
  4011fe:       75 e5                   jne    4011e5 <main+0x66>

  401200:       bf 30 20 40 00          mov    $0x402030,%edi
  401205:       e8 26 fe ff ff          callq  401030 <puts@plt> // printf

  40120a:       be 18 00 00 00          mov    $0x18,%esi // 参数n
  40120f:       48 89 e7                mov    %rsp,%rdi // 参数str
  401212:       e8 55 ff ff ff          callq  40116c <doSomething> // 调用doSomething

  401217:       bf 3d 20 40 00          mov    $0x40203d,%edi
  40121c:       e8 0f fe ff ff          callq  401030 <puts@plt>  // printf

  401221:       b8 00 00 00 00          mov    $0x0,%eax
  401226:       48 83 c4 28             add    $0x28,%rsp
  40122a:       c3                      retq   
  40122b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

000000000040116c <doSomething>:
  40116c:       48 83 ec 10             sub    $0x10,%rsp // 栈中开辟临时变量空间

  401170:       89 f2                   mov    %esi,%edx // 参数 n
  401172:       48 89 e6                mov    %rsp,%rsi // desc
  401175:       e8 d0 ff ff ff          callq  40114a <copy> // 调用copy

  40117a:       48 83 c4 10             add    $0x10,%rsp
  40117e:       c3                      retq

000000000040114a <copy>:
  40114a:       85 d2                   test   %edx,%edx
  40114c:       7e 1d                   jle    40116b <copy+0x21> // 如果参数n是0 直接返回

  40114e:       8d 4a ff                lea    -0x1(%rdx),%ecx // 参数n-1 因为从0开始循环
  401151:       b8 00 00 00 00          mov    $0x0,%eax // i = 0
  401156:       eb 03                   jmp    40115b <copy+0x11>
  401158:       48 89 d0                mov    %rdx,%rax
  40115b:       0f b6 14 07             movzbl (%rdi,%rax,1),%edx // src[n] -> 寄存器
  40115f:       88 14 06                mov    %dl,(%rsi,%rax,1) // 寄存器 -> desc[n]
  401162:       48 8d 50 01             lea    0x1(%rax),%rdx // ++i
  401166:       48 39 c8                cmp    %rcx,%rax
  401169:       75 ed                   jne    401158 <copy+0xe>

  40116b:       c3                      retq
  • -fno-stack-protector:禁用堆栈保护
  • 如果不优化用O0,不仅会push rip还会push rbp
  • 第一行sub $0x28,%rsp 在栈中开辟临时变量空间,其中0x28中是 (字符串长度24,16字节对齐到0x20) + (printf的0x8)
  • printf会在第一次调用的时候用malloc申请缓冲区,malloc会在分配的地址前预留2*sizeof(size_t)的空间维护malloc_chunk信息 。

如果看不懂汇编的可以看这个堆栈变换的示意图:
在这里插入图片描述
一开始attack函数的地址被放在buffer数组后8位,调用了doSomething后压栈了riptemp数组变量,结果字符串copybuffer数组比temp数组长的后8位也被拷贝过去了,由于关闭了栈保护,把原来的rip覆盖了。doSomething函数结束后就调用到attack函数了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

day01 - web开发简介

本课程涉及到的技术&#xff1a; Vue ElementUI/Html Js SpringBoot–Spring SpringMvc MyBatis(Plus) SSM Axios 学习路径&#xff1a; 前端主要&#xff1a; Html5css3JavaScript(JQuery)–>Vue(Node.js也可以学习一 下&#xff0c;服务端js)ElementUi(uni-app) 后端主要…

简单又便宜的实现电脑远程开机唤醒方法

现有的远程开机方案 1&#xff09;使用向日葵开机棒 缺点是比较贵一点&#xff0c;开机棒要一百多&#xff0c;而且查了评论发现挺多差评说不稳定&#xff0c;会有断联和无法唤醒的情况&#xff0c;而且设置也麻烦&#xff0c;还需要网卡支持WOL 2&#xff09;使用远程开机卡 …

自攻螺钉的世纪演变:探索关键设计与应用

自攻螺钉作为现代工业和建筑中的不可或缺的标准部件&#xff0c;经过了超过100年的发展和创新。从1914年最早的铁螺钉设计到今天的自钻自攻螺钉&#xff0c;自攻螺钉的设计不断优化&#xff0c;以适应更复杂的应用需求。本文将回顾自攻螺钉的演变历程&#xff0c;分析其设计原理…

[复健计划][紫书]Chapter 7 暴力求解法

7.1 简单枚举 例7-1 Division uva725 输入正整数n&#xff0c;按从小到大的顺序输出所有形如abcde/fghij n的表达式&#xff0c;其中a&#xff5e;j恰好为数字0&#xff5e;9的一个排列&#xff08;可以有前导0&#xff09;&#xff0c;2≤n≤79。枚举fghij&#xff0c;验证a…

OpenBayes 一周速览丨Ministral-8B革新侧端AI新体验!PsyDTCorpus心理咨询数据集上线,含5k个数字孪生对话数据

公共资源速递 This Weekly Snapshots &#xff01; 5 个数据集&#xff1a; * Labelme 图像标注数据集 * TIMIT 英语方言录音数据集 * Food-101 食品图像数据集 * SVHN 真实世界图像数据集 * PsyDTCorpus 心理咨询师数字孪生数据集 1 个模型&#xff1a; * Allegro 3…

如何修改网络ip地址:一步步指南‌

在当今这个数字化时代&#xff0c;网络已成为我们日常生活与工作中不可或缺的一部分。无论是浏览网页、在线办公还是享受流媒体服务&#xff0c;稳定的网络连接和适当的IP地址管理都是确保良好体验的关键。然而&#xff0c;出于隐私保护、绕过地理限制或测试网络环境等需要&…

论 ONLYOFFICE:开源办公套件的深度探索

公主请阅 引言第一部分&#xff1a;ONLYOFFICE 的历史背景1.1 开源软件的崛起1.2 ONLYOFFICE 的发展历程 第二部分&#xff1a;ONLYOFFICE 的核心功能2.1 文档处理2.2 电子表格2.3 演示文稿 第三部分&#xff1a;技术架构与兼容性3.1 技术架构3.2 兼容性 第四部分&#xff1a;部…

如何将现有VUE项目所有包更新到最新稳定版

更新有风险,Enter要谨慎!!! 要将项目中的所有 npm 包更新到最新稳定版&#xff0c;可以使用 npm-check-updates 工具。以下是具体步骤&#xff1a; 步骤一&#xff1a;安装 npm-check-updates 首先&#xff0c;全局安装 npm-check-updates 工具&#xff1a; npm install -g…

高德 阿里231滑块 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

特征检测与特征匹配方法笔记+代码分享

在一幅图像中&#xff0c;总能发现其独特的像素点&#xff0c;这些点可以被视为该图像的特征&#xff0c;我们称之为特征点。在计算机视觉领域中&#xff0c;基于特征点的图像特征匹配是一项至关重要的任务&#xff0c;因此&#xff0c;如何定义并识别一幅图像中的特征点显得尤…

【陕西】《陕西省省级政务信息化项目投资编制指南(建设类)(试行)》-省市费用标准解读系列07

《陕西省省级政务信息化项目投资编制指南&#xff08;建设类&#xff09;&#xff08;试行&#xff09;》规定了建设类项目的费用投资测算方法与计价标准&#xff0c;明确指出建设类项目费用包括项目建设费和项目建设其他费&#xff08;了解更多可直接关注咨询我们&#xff09;…

无人机干扰与抗干扰,无人机与反制设备的矛与盾

无人机干扰与抗干扰&#xff0c;以及无人机与反制设备之间的关系&#xff0c;可以形象地比喻为矛与盾的较量。以下是对这两方面的详细探讨&#xff1a; 一、无人机干扰与抗干扰 1. 无人机干扰技术 无人机干扰技术是指通过各种手段对无人机系统进行干扰&#xff0c;使其失去正…

Github配置ssh key原理及操作步骤

文章目录 配置SSH第一步&#xff1a;检查本地主机是否已经存在ssh key第二步&#xff1a;生成ssh key第三步&#xff1a;获取ssh key公钥内容第四步&#xff1a;Github账号上添加公钥第五步&#xff1a;验证是否设置成功验证原理 往github上push项目的时候&#xff0c;如果走ht…

MySQL日期类型选择建议

我们平时开发中不可避免的就是要存储时间&#xff0c;比如我们要记录操作表中这条记录的时间、记录转账的交易时间、记录出发时间、用户下单时间等等。你会发现时间这个东西与我们开发的联系还是非常紧密的&#xff0c;用的好与不好会给我们的业务甚至功能带来很大的影响。所以…

【Ant.designpro】上传图片

文章目录 一、前端二、后端 一、前端 fieldProps:可以监听并且获取到组件输入的内容 action{“/api/upload_image”} 直接调用后端接口 <ProFormUploadButtonlabel{"上传手续图片"}name{"imgs"}action{"/api/upload_image"}max{5} fieldPro…

vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法

1、先上个截图&#xff1a; 说明&#xff1a;拖动上面的分隔栏就可以实现&#xff0c;改变左右区域的大小。 2、上面的例子来自官网的&#xff1a; Container 布局容器 | Element Plus 3、拖动的效果来自&#xff1a; https://juejin.cn/post/7029640316999172104#heading-1…

Android Studio加载旧的安卓工程项目报错处理

文章目录 Invalid Gradle JDK configuration foundNDK not configuredCMake 3.10.2 was not found安装cmake适配cmake版本号 com.intellij.openapi.externalSystem.model.ExternalSystemExceptiongradle版本过低或下载不了下载gradle与依赖库超时替换gradle国内源替换Maven 仓库…

Qt中的Model与View 4:QStandardItemModel与QTableView

目录 QStandardItemModel API QTableView 导航 视觉外观 坐标系统 API 样例&#xff1a;解析一个表格txt文件 QStandardItemModel QStandardItemModel 可用作标准 Qt 数据类型的存储库。它是模型/视图类之一&#xff0c;是 Qt 模型/视图框架的一部分。它提供了一种基于…

web——sqliabs靶场——第一关

今天开始搞这个靶场&#xff0c;从小白开始一点点学习,加油&#xff01;&#xff01;&#xff01;&#xff01; 1.搭建靶场 注意点&#xff1a;1.php的版本问题&#xff0c;要用老版本 2.小p要先改数据库的密码&#xff0c;否则一直显示链接不上数据库 2.第一道题&#xff0…

Markdown快速上手(typora)

一级标题~六级标题 可以选中文本在这里直接设置&#xff0c;后面也有快捷键&#xff0c;也可以使用其语法&#xff0c;一个#&#xff0c;对应一级标题&#xff0c;两个#&#xff0c;对应二级标题&#xff0c;等。 我这里使用Ctrl1没生效是因为快捷键冲突&#xff0c;也需要注意…