【C++】汇编角度分析栈攻击

栈攻击

  • 介绍原理
  • 示例代码
  • 汇编分析

介绍原理

核心原理是通过 缓冲区溢出(Buffer Overflow) 等漏洞,覆盖栈上的关键数据(如返回地址、函数指针),从而改变程序执行流程;

在 C++ 中,每个函数调用都会在栈上创建一个栈帧(Stack Frame),包含:

  • 局部变量:函数内定义的变量。
  • 函数参数:调用函数时传递的参数。
  • 返回地址:函数执行完后返回的地址(保存在 EIP 寄存器)。
  • 帧指针(EBP):指向当前栈帧的基址。
    栈内存是向下增长的(从高地址向低地址)

缓冲区溢出攻击
当程序向缓冲区写入数据时,若未检查输入长度,可能导致数据超出缓冲区边界,覆盖相邻的栈内存区域。攻击者可利用这一点:

  1. 覆盖返回地址为恶意代码的地址。放置攻击者指定的地址(如 shellcode 的起始地址
  2. 在栈上注入恶意代码(如 shellcode)。
  3. 触发溢出:当函数返回时,程序ret到攻击者指定的地址执行;

示例代码

下面示例代码就是通过缓冲区溢出覆盖掉栈的ret返回的地址从而改变函数返回后程序执行的地址(篡改为攻击函数地址);
大致流程:

  1. 先得到攻击函数Hack地址
  2. 调用count函数时候通过数组溢出方式,通过分析汇编代码,将汇编ret的地址修改为我们的Hack函数的地址
  3. 如此,count函数返回后程序就会沿着我们修改的Hack方向运行;
#include <iostream>
#include <iomanip>void Hack()
{unsigned long long x = 0;for (int i = 0; true; i++){if (i % 100000000 == 0){system("cls");std::cout << "\n■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n";std::cout << "\n 你的系统已经被我们拿下! hacked by 黑兔档案局:[ID:000001 ]\n";std::cout << "\n\\>正在传输硬盘数据....已经传输" << x++ << "个文件......\n\n";std::cout << std::setfill('>')<< std::setw(x % 60) << "\n";std::cout << "\n\\>摄像头已启动!<==============\n\n";std::cout << std::setfill('#') << std::setw(x % 60) << "\n";std::cout << "\n\\>数据传输完成后将启动自毁程序!CPU将会温度提升到200摄氏度\n";std::cout << "\n■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n";}}
}int GetAge()
{int rt;std::cout << "请输入学员的年龄:";std::cin >> rt;return rt;
}int count()
{int i{};int total{};int age[10]{};do{age[i] = GetAge();total += age[i];//将AGE[I]保存到数据库中} while (age[i++]);return total;
}int main()
{std::cout << "======= 驴百万学院 学员总年龄统计计算系统 =====\n";std::cout << "\n                API:"<<Hack<<std::endl;std::cout << "\n[说明:最多输入10个学员的信息,当输入0时代表输入结束]\n\n";std::cout << "\n驴百万学院的学员总年龄为:" << count();
}

汇编分析

直接从count函数汇编入手:

int count()42: {
00061200  push        ebp  //当前函数调用前的基址指针(Base Pointer,通常用来指向当前函数的栈帧)压入栈中,以便后续在函数结束时能够恢复到调用前的状态。
00061201  mov         ebp,esp  //将当前栈指针(Stack Pointer,指向当前栈顶)的值赋给基址指针 ebp,这样 ebp 现在指向当前函数count的栈帧
00061203  sub         esp,34h  //esp=esp-52,这条指令将栈指针 esp 减去 0x34h(52 的十进制值),这样就为当前函数的栈帧分配了 52 字节的空间。在函数执行过程中,局部变量和其他数据将会存储在这段空间中。43: 	int i{};
00061206  mov         dword ptr [i],0  // 0移动到变量 i 所在的内存位置。dword ptr 来指示操作数(内存里的数据)的大小为双字(32 位,4字节),这是因为 i 是一个整数类型变量。44: 	int total{};
0006120D  mov         dword ptr [total],0  45: 	int age[10]{};
00061214  xor         eax,eax  //将寄存器 eax 与自身进行异或操作,结果存储回 eax。这个操作的目的是将 eax 清零,因为在这段代码中,eax 被用来存储数组 age 的起始地址。
00061216  mov         dword ptr [age],eax  
00061219  mov         dword ptr [ebp-30h],eax  //48字节偏移量
0006121C  mov         dword ptr [ebp-2Ch],eax //44 
0006121F  mov         dword ptr [ebp-28h],eax  
00061222  mov         dword ptr [ebp-24h],eax  
00061225  mov         dword ptr [ebp-20h],eax  
00061228  mov         dword ptr [ebp-1Ch],eax  
0006122B  mov         dword ptr [ebp-18h],eax  
0006122E  mov         dword ptr [ebp-14h],eax  
00061231  mov         dword ptr [ebp-10h],eax  //16

在这里插入图片描述
栈底ebp存的就是count函数的下一条地址,我们目的是修改这一个地址;

这段代码对应函数栈如下:

在这里插入图片描述

46: 	do47: 	{48: 		age[i] = GetAge();
00061234  call        GetAge (0611D0h)  //调用了一个函数 GetAge,并将返回值存储在寄存器 eax 中。
00061239  mov         ecx,dword ptr [i]  //将变量 i 的值加载到寄存器 ecx 中  ecx=i =0  ecx=i=1
0006123C  mov         dword ptr age[ecx*4],eax  //此时将寄存器 eax 中的年龄age存储到 age[ecx*4] 中,age[ecx*4]将age数组的内存地址偏移ecx*4个字节。此时ecx*4 是因为 age 是一个数组,每个元素占据 4 个字节。 age[0] = eax =age0 age[1] = eax =age149: 		total += age[i];
00061240  mov         edx,dword ptr [i]  //将变量 i 的值加载到寄存器 edx 中  edx =i= 0   edx =i= 1
00061243  mov         eax,dword ptr [total] // 将变量 total 的值加载到寄存器 eax 中  eax = total
00061246  add         eax,dword ptr age[edx*4]  //[]里的理解为字节的位置,而不是元素,将 age[i] 的值加到 total 中     eax = eax+age[0]+age[1]
0006124A  mov         dword ptr [total],eax //将寄存器 eax 中的值存储回变量 total 中。    total = eax50: 		//将AGE[I]保存到数据库中51: 	} while (age[i++]);  //就是让i++并且判断是否这次输入的age[i]==0
0006124D  mov         ecx,dword ptr [i]  //将变量 i 的值加载到寄存器 ecx 中    ecx=i=0
00061250  mov         edx,dword ptr age[ecx*4]  //V将 age[i] 的值加载到寄存器 edx 中  edx = age[0]//edx值放在[ebp-0Ch]这篇内存应该是专门为了与0比较开辟的内存
00061254  mov         dword ptr [ebp-0Ch],edx  //将寄存器 edx 中的值存储到内存中的位置 [ebp-0Ch]。ebp-12 
00061257  mov         eax,dword ptr [i]  //将变量 i 的值加载到寄存器 eax 中   eax = i =0
0006125A  add         eax,1  //将寄存器 eax 中的值加 1		eax = eax+1
0006125D  mov         dword ptr [i],eax  //将寄存器 eax 中的值存储回变量 i 中   i = eax
00061260  cmp         dword ptr [ebp-0Ch],0 //将内存中的位置 [ebp-0Ch]ebp-12 的值与 0 比较    age[0]与0比较
00061264  jne         count+34h (061234h)  //如果不相等,则跳转到 count+34h(52) 处执行  //查询 count  0x00061200h  +34h后是0x00061234。跳到了call GetAge处52: 	return total;
00061266  mov         eax,dword ptr [total]  // total 变量的值加载到寄存器 eax 中53: }
//函数清尾
00061269  mov         esp,ebp  
0006126B  pop         ebp  //在pop ebp指令中,ebp是一个操作数,指示将栈顶元素弹出并将其存储到ebp寄存器中
0006126C  ret  //此时已经返回了[total]算出了正确total,运行结束!

在这里插入图片描述

注意:下面这张图的代码age数组是改为5的,对应下面图片,最后输入的就是Hack的API地址,此时替换为了原来ret指向的地址;
在这里插入图片描述

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

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

相关文章

访问 Docker 官方镜像源(包括代理)全部被“重置连接”或超时

华为云轻量应用服务器&#xff08;Ubuntu 系统&#xff09; 遇到的问题是&#xff1a; &#x1f512; 访问 Docker 官方镜像源&#xff08;包括代理&#xff09;全部被“重置连接”或超时了&#xff0c;说明你这台服务器的出境网络对这些国外域名限制很严格&#xff0c;常见于华…

Java语言

本文来源 &#xff1a; 腾讯元宝 Java是一种面向对象、跨平台的高级编程语言&#xff0c;最初由Sun Microsystems&#xff08;现为Oracle公司所有&#xff09;于1995年推出&#xff0c;广泛应用于Web开发、移动应用、大数据处理、嵌入式系统等领域。以下是其核心特点和应用概述…

无偿帮写毕业论文(看不懂的可以私信博主)

以下教程教你如何利用相关网站和AI免费帮你写一个毕业论文。毕竟毕业论文只要过就行&#xff0c;脱产学习这么多年&#xff0c;终于熬出头了&#xff0c;完成毕设后有空就去多看看亲人好友&#xff0c;祝好&#xff01; 一、找一个论文模板 废话不多说&#xff0c;先上干货Ov…

python打卡day26

函数、参数、变量 知识点回顾&#xff1a; 函数的定义变量作用域&#xff1a;局部变量和全局变量函数的参数类型&#xff1a;位置参数、默认参数、不定参数传递参数的手段&#xff1a;关键词参数传递参数的顺序&#xff1a;同时出现三种参数类型时 def function_name(parameter…

LeetCode 热题 100 437. 路径总和 III

LeetCode 热题 100 | 437. 路径总和 III 大家好&#xff0c;今天我们来解决一道经典的二叉树问题——路径总和 III。这道题在 LeetCode 上被标记为中等难度&#xff0c;要求计算二叉树中节点值之和等于给定目标值 targetSum 的路径数目。 问题描述 给定一个二叉树的根节点 ro…

vue3学习-局部使用vue框架案例

目录 局部使用vue框架步骤 简单案例1 简单案例2【 结构化赋值语法】 简单案例3【使用模块化开发模式】 基本数据的简单应用&#xff0c;对象的简单应用 数组的简单应用 局部使用vue框架步骤 1 引用 vue框架的核心文件和 涉及ES6语法的文件 注意&#xff1a;这里文件&am…

初识Linux · IP分片

目录 前言&#xff1a; IP分片 分片vs不分片 如何分片 分片举例 三个字段 前言&#xff1a; 前文IP协议上和IP协议下我们已经把IP协议的报头的大多数字段介绍了&#xff0c;唯独有三个字段现在还有介绍&#xff0c;即16位标识&#xff0c;8位协议&#xff0c;13位片偏移…

u3d 定义列表详细过程

层级结构 - Canvas - Scroll View - Viewport - Content (Vertical Layout Group) - Item1 (Prefab) - Item2 (Prefab) ... 详细设置步骤 1. 创建 Canvas 2. 添加 Scroll View 组件 3. 在 Scroll View 下创建 Content 子对象 4. 添加 …

产品方法论与 AI Agent 技术的深度融合:从决策智能到价值创造

一、引言&#xff1a;智能化时代的产品范式革命 在数字化转型的深水区&#xff0c;产品开发正经历着从 “功能定义” 到 “体验设计” 再到 “智能演化” 的范式跃迁。麦肯锡 2024 年报告指出&#xff0c;采用 AI 驱动产品方法论的企业&#xff0c;新品研发周期平均缩短 40%&a…

力扣.1471数组的k个最强值,力扣.1471数组的k个最强值力扣1576.替换所有的问号力扣1419.数青蛙​编辑力扣300.最长递增子序列

目录 力扣.1471数组的k个最强值 力扣1576.替换所有的问号 力扣1419.数青蛙​编辑 力扣300.最长递增子序列 力扣.1471数组的k个最强值 class Solution {public static int[] getStrongest(int[] arr,int k) {if(karr.length){return arr;}int []retnew int[k];int narr.lengt…

使用docker安装clickhouse集群

1、简介 clickhouse 作为大数据场景中&#xff0c;实现快速检索的常用列式存储数据库&#xff0c;采用物理机部署&#xff0c;会在数据量大的场景中&#xff0c;物理机器存储达到阈值需要扩容&#xff0c;会带来比较大的问题&#xff0c;因此&#xff0c;使用docker部署clickho…

package-lock.json能否直接删除?

package-lock.json能否直接删除&#xff1f; package-lock.json 生成工具&#xff1a;由 npm 自动生成。 触发条件&#xff1a;当运行 npm install 时&#xff0c;如果不存在 package-lock.json&#xff0c;npm 会创建它&#xff1b;如果已存在&#xff0c;npm 会根据它精确安…

如何在 Windows 命令提示符中创建多个文件夹和多个文件

如何在 Windows 命令提示符中创建多个文件夹和多个文件 虽然大多数用户习惯使用 Windows 图形界面来创建文件夹&#xff0c;但如果你需要一次性创建多个文件夹或文件&#xff0c;如同在类Unix系统中可以使用mkdir和touch命令一样&#xff0c;windows下也有创建目录和文件的对应…

leetcode - 滑动窗口问题集

目录 前言 题1 长度最小的子数组&#xff1a; 思考&#xff1a; 参考代码1&#xff1a; 参考代码2&#xff1a; 题2 无重复字符的最长子串&#xff1a; 思考&#xff1a; 参考代码1&#xff1a; 参考代码2&#xff1a; 题3 最大连续1的个数 III&#xff1a; 思考&am…

Ubuntu20.04下如何源码编译Carla,使用UE4源码开跑,踩坑集合

一、简介 作为一个从事算法研究的人员,无人驾驶仿真一直是比较重要的一部分,但是现在比较常见的算法验证都是在carla这个开源仿真平台上做的,所以我有二次开发carla的需求,今天就来讲讲编译CARLA。 网上的教材很多,但还是推荐大家看官网教程:Linux build - CARLA Simul…

Linux云计算训练营笔记day09(MySQL数据库)

Linux云计算训练营笔记day09&#xff08;MySQL数据库&#xff09; 目录 Linux云计算训练营笔记day09&#xff08;MySQL数据库&#xff09;外键约束数据的导入和导出数据的导出数据的导入 DQL 数据查询语言查指定字段查所有字段where 过滤条件and 和 orin 和 not inbetween...an…

对心理幸福感含义的探索 | 幸福就是一切吗?

注&#xff1a;机翻&#xff0c;未校。 Happiness Is Everything, or Is It? Explorations on the Meaning of Psychological Well-Being 幸福就是一切吗&#xff1f;对心理幸福感含义的探索 Journal of Personality and Social Psychology 1989, Vol. 57, No. 6,1069-1081 …

零基础学Java——第十一章:实战项目 - 微服务入门

第十一章&#xff1a;实战项目 - 微服务入门 随着互联网应用的复杂性不断增加&#xff0c;单体应用&#xff08;Monolithic Application&#xff09;在可扩展性、可维护性、技术栈灵活性等方面逐渐暴露出一些问题。微服务架构&#xff08;Microservices Architecture&#xff…

git 本地提交后修改注释

dos命令行进入目录&#xff0c;idea可以点击Terminal 进入命令行 git commit --amend -m "修改内容"

Python训练打卡Day22

复习日&#xff1a; 1.标准化数据&#xff08;聚类前通常需要标准化&#xff09; scaler StandardScaler() X_scaled scaler.fit_transform(X) StandardScaler() &#xff1a;这部分代码调用了 StandardScaler 类的构造函数。在Python中&#xff0c;当你在类名后面加上括号…