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

news2025/5/16 19:05:45

栈攻击

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

介绍原理

核心原理是通过 缓冲区溢出(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: 	do
    47: 	{
    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 =age1
    49: 		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 = eax
    50: 		//将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.coloradmin.cn/o/2377083.html

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

相关文章

Vue 3 打开 el-dialog 时使 el-input 获取焦点

运行代码&#xff1a;https://andi.cn/page/622178.html 效果&#xff1a;

C++23 views::repeat (P2474R2) 深入解析

文章目录 引言C20 Ranges库回顾什么是Rangesstd::views的作用 views::repeat概述基本概念原型定义工作原理应用场景初始化容器模拟测试数据 总结 引言 在C的发展历程中&#xff0c;每一个新版本都会带来一系列令人期待的新特性&#xff0c;这些特性不仅提升了语言的性能和表达…

OpenCv高阶(4.0)——案例:海报的透视变换

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

光谱相机的图像预处理技术

光谱相机的图像预处理技术旨在消除噪声、增强有效信息&#xff0c;为后续分析提供高质量数据。 一、预处理流程与技术要点 ‌辐射校正‌ ‌辐射定标‌&#xff1a;将图像灰度值转换为绝对辐射亮度&#xff0c;常用反射率法、辐亮度法和辐照度法消除传感器响应差异&#xff0…

k8s监控方案实践补充(一):部署Metrics Server实现kubectl top和HPA支持

k8s监控方案实践补充&#xff08;一&#xff09;&#xff1a;部署Metrics Server实现kubectl top和HPA支持 文章目录 k8s监控方案实践补充&#xff08;一&#xff09;&#xff1a;部署Metrics Server实现kubectl top和HPA支持一、Metrics Server简介二、Metrics Server实战部署…

嵌入式调试新宠!J-Scope:免费+实时数据可视化,让MCU调试效率飙升!

&#x1f4cc; 痛点直击&#xff1a;调试还在用“断点打印”&#xff1f; 嵌入式开发中&#xff0c;你是否也经历过这些崩溃瞬间&#xff1f; 想实时观察变量变化&#xff0c;代码里插满printf&#xff0c;结果拖垮系统性能&#xff1f; 断点调试打断程序运行&#xff0c;时序…

微信小程序学习之搜索框

1、第一步&#xff0c;我们在index.json中引入vant中的搜索框控件&#xff1a; {"usingComponents": {"van-search": "vant/weapp/search/index"} } 2、第二步&#xff0c;直接在index.wxml中添加布局&#xff1a; <view class"index…

Altium Designer AD如何输出PIN带网络名的PDF装配图

Altium Designer AD如何输出PIN带网络名的PDF装配图 文描述在Altium Designer版本中设置焊盘网络名时遇到的问题&#xff0c;网络名大小不一致&#xff0c;部分PAD的网络名称未显示&#xff0c;可能涉及字符大小设置和版本差异。 参考 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 我打包好放这了&#xff0c;VMware 和 CentOS7 &#xff0c;下载即可。 关于VMware Workstation Pro 17.6.3&#xff0c;傻瓜式安装即可。 CentO…

Python训练打卡Day22

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

Cold Diffusion: Inverting Arbitrary Image Transforms Without Noise论文阅读

冷扩散&#xff1a;无需噪声的任意图像变换反转 摘要 标准扩散模型通常涉及两个核心步骤&#xff1a;图像降质 &#xff08;添加高斯噪声&#xff09;和图像恢复 &#xff08;去噪操作&#xff09;。本文发现&#xff0c;扩散模型的生成能力并不强烈依赖于噪声的选择&#xf…

嵌软面试每日一阅----通信协议篇(二)之TCP

一. TCP和UDP的区别 可靠性 TCP&#xff1a;✅ 可靠传输&#xff08;三次握手 重传机制&#xff09; UDP&#xff1a;❌ 不可靠&#xff08;可能丢包&#xff09; 连接方式 TCP&#xff1a;面向连接&#xff08;需建立/断开连接&#xff09; UDP&#xff1a;无连接&#xff0…

机器学习 --- 模型选择与调优

机器学习 — 模型选择与调优 文章目录 机器学习 --- 模型选择与调优一&#xff0c;交叉验证1.1 保留交叉验证HoldOut1.2 K-折交叉验证(K-fold)1.3 分层k-折交叉验证Stratified k-fold 二&#xff0c;超参数搜索三&#xff0c;鸢尾花数据集示例四&#xff0c;现实世界数据集示例…

AGI大模型(15):向量检索之调用ollama向量数据库

这里介绍将向量模型下载到本地,这里使用ollama,现在本地安装ollama,这里就不过多结束了。直接从下载开始。 1 下载模型 首先搜索模型,这里使用bge-large模型,你可以根据自己的需要修改。 点击进入,复制命令到命令行工具中执行。 安装后查看: 2 代码实现 先下载ollama…

什么是Agentic AI(代理型人工智能)?

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

day 17 无监督学习之聚类算法

一、聚类流程 1. 利用聚类发现数据模式 无监督算法中的聚类&#xff0c;目的就是将数据点划分成不同的组或 “簇”&#xff0c;使得同一簇内的数据点相似度较高&#xff0c;而不同簇的数据点相似度较低&#xff0c;从而发现数据中隐藏的模式。 2. 对聚类后的类别特征进行可视…

时源芯微| KY键盘接口静电浪涌防护方案

KY键盘接口静电浪涌防护方案通过集成ESD保护元件、电阻和连接键&#xff0c;形成了一道有效的防护屏障。当键盘接口受到静电放电或其他浪涌冲击时&#xff0c;该方案能够迅速将过电压和过电流引导至地&#xff0c;从而保护后续电路免受损害。 ESD保护元件是方案中的核心部分&a…

CodeBuddy编程新范式

不会写&#xff1f;不想写&#xff1f; 腾讯推出的CodeBuddy彻底解放双手。 示例 以下是我对CodeBuddy的一个小体验。 我只用一行文字对CodeBuddy说明了一下我的需求&#xff0c;剩下的全部就交给了CodeBuddy&#xff0c;我需要做的就是验收结果即可。 1.首先CodeBuddy会对任…

小刚说C语言刷题—1088求两个数M和N的最大公约数

1.题目描述 求两个正整数 M 和 N 的最大公约数(M&#xff0c;N都在长整型范围内&#xff09; .输入 输入一行&#xff0c;包括两个正整数。 输出 输出只有一行&#xff0c;包括1个正整数。 样例 输入 45 60 输出 15 2.参考代码(C语言版) #include <stdio.h> …

【LLIE专题】基于码本先验与生成式归一化流的低光照图像增强新方法

GLARE: Low Light Image Enhancement via Generative Latent Feature based Codebook Retrieval&#xff08;2024&#xff0c;ECCV&#xff09; 专题介绍一、研究背景二、GLARE方法阶段一&#xff1a;正常光照代码本学习&#xff08;Normal-Light Codebook Learning&#xff09…