【C++】汇编角度分析栈攻击
栈攻击
- 介绍原理
- 示例代码
- 汇编分析
介绍原理
核心原理是通过 缓冲区溢出(Buffer Overflow) 等漏洞,覆盖栈上的关键数据(如返回地址、函数指针),从而改变程序执行流程;
在 C++ 中,每个函数调用都会在栈上创建一个栈帧(Stack Frame),包含:
- 局部变量:函数内定义的变量。
- 函数参数:调用函数时传递的参数。
- 返回地址:函数执行完后返回的地址(保存在 EIP 寄存器)。
- 帧指针(EBP):指向当前栈帧的基址。
栈内存是向下增长的(从高地址向低地址)
缓冲区溢出攻击
当程序向缓冲区写入数据时,若未检查输入长度,可能导致数据超出缓冲区边界,覆盖相邻的栈内存区域。攻击者可利用这一点:
- 覆盖返回地址为恶意代码的地址。放置攻击者指定的地址(如 shellcode 的起始地址
- 在栈上注入恶意代码(如 shellcode)。
- 触发溢出:当函数返回时,程序ret到攻击者指定的地址执行;
示例代码
下面示例代码就是通过缓冲区溢出覆盖掉栈的ret返回的地址从而改变函数返回后程序执行的地址(篡改为攻击函数地址);
大致流程:
- 先得到攻击函数Hack地址
- 调用count函数时候通过数组溢出方式,通过分析汇编代码,将汇编ret的地址修改为我们的Hack函数的地址
- 如此,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指向的地址;
相关文章:

【C++】汇编角度分析栈攻击
栈攻击 介绍原理示例代码汇编分析 介绍原理 核心原理是通过 缓冲区溢出(Buffer Overflow) 等漏洞,覆盖栈上的关键数据(如返回地址、函数指针),从而改变程序执行流程; 在 C 中,每个…...

Vue 3 打开 el-dialog 时使 el-input 获取焦点
运行代码:https://andi.cn/page/622178.html 效果:...

C++23 views::repeat (P2474R2) 深入解析
文章目录 引言C20 Ranges库回顾什么是Rangesstd::views的作用 views::repeat概述基本概念原型定义工作原理应用场景初始化容器模拟测试数据 总结 引言 在C的发展历程中,每一个新版本都会带来一系列令人期待的新特性,这些特性不仅提升了语言的性能和表达…...
HTML5 定位详解:相对定位、绝对定位和固定定位
在HTML5和CSS中,定位(positioning)是控制元素在页面上位置的重要机制。主要有四种定位方式:静态定位(static)、相对定位(relative)、绝对定位(absolute)和固定定位(fixed)。下面我将详细讲解这三种非静态定位方式,并提供相应的源代码示例。 …...

OpenCv高阶(4.0)——案例:海报的透视变换
文章目录 前言一、工具函数模块1.1 图像显示函数1.2 保持宽高比的缩放函数1.3 坐标点排序函数 二、透视变换核心模块2.1 四点透视变换实现 三、主流程技术分解3.1 图像预处理3.2 轮廓检测流程3.3 最大轮廓处理 四、后处理技术4.1 透视变换4.2 形态学处理 五、完整代码总结 前言…...

光谱相机的图像预处理技术
光谱相机的图像预处理技术旨在消除噪声、增强有效信息,为后续分析提供高质量数据。 一、预处理流程与技术要点 辐射校正 辐射定标:将图像灰度值转换为绝对辐射亮度,常用反射率法、辐亮度法和辐照度法消除传感器响应差异࿰…...
CSS 溢出内容处理、可见性控制与盒类型设置深度解析
CSS溢出内容处理、可见性控制与盒类型设置深度解析 一、溢出内容处理(Overflow) 在网页设计中,内容超出容器边界是常见问题。CSS提供了overflow属性及其变体来控制这种情况。 1.1 溢出基本属性 核心属性: overflow: visible&…...

k8s监控方案实践补充(一):部署Metrics Server实现kubectl top和HPA支持
k8s监控方案实践补充(一):部署Metrics Server实现kubectl top和HPA支持 文章目录 k8s监控方案实践补充(一):部署Metrics Server实现kubectl top和HPA支持一、Metrics Server简介二、Metrics Server实战部署…...
从代码学习深度学习 - 实战 Kaggle 比赛:图像分类 (CIFAR-10 PyTorch版)
文章目录 前言1. 读取并整理数据集1.1 读取标签文件1.2 划分训练集和验证集1.3 整理测试集1.4 执行数据整理2. 图像增广2.1 训练集图像变换2.2 测试集(和验证集)图像变换3. 读取数据集3.1 创建 Dataset 对象3.2 创建 DataLoader 对象4. 定义模型4.1 获取 ResNet-18 模型4.2 损…...
【数据结构】二分查找5.12
Basic 需求:在有序数组A内,查找值target 如果找到返回索引 如果找不到返回-1 算法描述: 前提:给定一个内含n个元素的有序数组A(升序),一个待查找值 设置两个索引:i0;jn-1; 如果…...
深入探索向量数据库:构建智能应用的新基础
📌 友情提示: 本文内容由银河易创AI(https://ai.eaigx.com)创作平台的gpt-4-turbo模型辅助生成,旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证,建议读者通过官方文档或实践进一步确认…...
Swagger go中文版本手册
Swaggo(github.com/swaggo/swag)的注解语法是基于 OpenAPI 2.0 (以前称为 Swagger 2.0) 规范的,并添加了一些自己的约定。 主要官方文档: swaggo/swag GitHub 仓库: 这是最权威的来源。 链接: https://github.com/swaggo/swag重点关注: README.md: 包含了基本的安装、使用…...
Cloudera CDP 7.1.3 主机异常关机导致元数据丢失,node不能与CM通信
问题描述 plaintext ERROR Could not load post-deployment data from /var/run/cloudera-scm-agent/process/ccdeploy_hadoop-conf_etchadoopconf.cloudera.yarn_-8903374259073700469 IOError: [Errno 2] No such file or directory: /var/run/cloudera-scm-agent/proce…...
Redis特性与应用
1、分布式缓存与redis 2、redis数据结构和客户端集成 3、缓存读写模式与数据一致性 本地缓存:Hash Map、Ehcache、Caffeine、Google Guava 分布式缓存:Memcached、redis、Hazelcast、Apache ignite redis:基于键值对内存数据库,支…...

嵌入式调试新宠!J-Scope:免费+实时数据可视化,让MCU调试效率飙升!
📌 痛点直击:调试还在用“断点打印”? 嵌入式开发中,你是否也经历过这些崩溃瞬间? 想实时观察变量变化,代码里插满printf,结果拖垮系统性能? 断点调试打断程序运行,时序…...

微信小程序学习之搜索框
1、第一步,我们在index.json中引入vant中的搜索框控件: {"usingComponents": {"van-search": "vant/weapp/search/index"} } 2、第二步,直接在index.wxml中添加布局: <view class"index…...

Altium Designer AD如何输出PIN带网络名的PDF装配图
Altium Designer AD如何输出PIN带网络名的PDF装配图 文描述在Altium Designer版本中设置焊盘网络名时遇到的问题,网络名大小不一致,部分PAD的网络名称未显示,可能涉及字符大小设置和版本差异。 参考 1.AD导出PCB装配图 https://blog.csd…...

VMware虚拟机 安装 CentOS 7
原文链接: VMware虚拟机 安装 CentOS 7 安装准备 软件: VMware Workstation Pro 17.6.3 镜像: CentOS-7.0-1406-x86_64-DVD.iso 我打包好放这了,VMware 和 CentOS7 ,下载即可。 关于VMware Workstation Pro 17.6.3,傻瓜式安装即可。 CentO…...
关于高并发GIS数据处理的一点经验分享
1、背景介绍 笔者过去几年在参与某个大型央企的项目开发过程中,遇到了十分棘手的难题。其与我们平常接触的项目性质完全不同。在一般的项目中,客户一般只要求我们能够通过桌面软件对原始数据进行加工处理,将各类地理信息数据加工处理成地图/场景和工作空间,然后再将工作空…...
Python训练打卡Day22
复习日: 1.标准化数据(聚类前通常需要标准化) scaler StandardScaler() X_scaled scaler.fit_transform(X) StandardScaler() :这部分代码调用了 StandardScaler 类的构造函数。在Python中,当你在类名后面加上括号…...

Cold Diffusion: Inverting Arbitrary Image Transforms Without Noise论文阅读
冷扩散:无需噪声的任意图像变换反转 摘要 标准扩散模型通常涉及两个核心步骤:图像降质 (添加高斯噪声)和图像恢复 (去噪操作)。本文发现,扩散模型的生成能力并不强烈依赖于噪声的选择…...
2025认证杯数学建模第二阶段C题:化工厂生产流程的预测和控制,思路+模型+代码
2025认证杯数学建模第二阶段思路模型代码,详细内容见文末名片 一、探秘化工世界:问题背景大揭秘 在 2025 年 “认证杯”数学中国数学建模网络挑战赛第二阶段 C 题中,我们一头扎进了神秘又复杂的化工厂生产流程预测与控制领域。想象一下&…...
物联网驱动的共享充电站系统:智能充电的实现原理与技术解析!
随着新能源汽车的快速普及,共享充电站系统作为其核心基础设施,正通过物联网技术的深度赋能,实现从“传统充电”到“智能充电”的跨越式升级。本文将从系统架构、核心技术、优化策略及实际案例等角度,解析物联网如何驱动共享充电站…...

嵌软面试每日一阅----通信协议篇(二)之TCP
一. TCP和UDP的区别 可靠性 TCP:✅ 可靠传输(三次握手 重传机制) UDP:❌ 不可靠(可能丢包) 连接方式 TCP:面向连接(需建立/断开连接) UDP:无连接࿰…...

机器学习 --- 模型选择与调优
机器学习 — 模型选择与调优 文章目录 机器学习 --- 模型选择与调优一,交叉验证1.1 保留交叉验证HoldOut1.2 K-折交叉验证(K-fold)1.3 分层k-折交叉验证Stratified k-fold 二,超参数搜索三,鸢尾花数据集示例四,现实世界数据集示例…...
《Python星球日记》 第58天:Transformer 与 BERT
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、引言一、Transformer 架构简介1. 自注意力机制(Self-Attention)工作原理2. 多头注意力与位置编码多头注意力机制位置编码二、BERT 的结构…...
2900. 最长相邻不相等子序列 I
2900. 最长相邻不相等子序列 I class Solution:def getLongestSubsequence(self, words: List[str], groups: List[int]) -> List[str]:n len(groups) # 获取 groups 列表的长度ans [] # 初始化一个空列表,用于存储结果for i, g in enumerate(groups): # 遍…...

AGI大模型(15):向量检索之调用ollama向量数据库
这里介绍将向量模型下载到本地,这里使用ollama,现在本地安装ollama,这里就不过多结束了。直接从下载开始。 1 下载模型 首先搜索模型,这里使用bge-large模型,你可以根据自己的需要修改。 点击进入,复制命令到命令行工具中执行。 安装后查看: 2 代码实现 先下载ollama…...
Python网络请求利器:urllib库深度解析
一、urllib库概述 urllib是Python内置的HTTP请求库,无需额外安装即可使用。它由四个核心模块构成: urllib.request:发起HTTP请求的核心模块urllib.error:处理请求异常(如404、超时等)…...

什么是Agentic AI(代理型人工智能)?
什么是Agentic AI(代理型人工智能)? 一、概述 Agentic AI(代理型人工智能)是一类具备自主决策、目标导向性与持续行动能力的人工智能系统。与传统AI系统依赖外部输入和显式命令不同,Agentic AI在设定目标…...