c++异常处理-漏洞利用

文章目录

  • 参考
  • 异常处理顺序
  • eh_frame段的作用
      • 编译过程中的`.eh_frame`生成
      • 运行时异常处理
  • 堆栈展开
  • 简单劫持
    • rbp
    • ret
  • chop
      • 1. 异常发生时的堆栈保存
      • 2. 查找`.eh_frame`信息
      • 3. 解析FDE并恢复CFA
      • 4. 恢复寄存器
      • 5. 堆栈展开
      • 6. 转向异常处理逻辑
  • 先忙awd了以后补

参考

https://xz.aliyun.com/t/12967?time__1311=mqmhqIx%2BODkKDsD7G30%3D3DtQp%2BnYFeD&alichlgref=https%3A%2F%2Fwww.google.com.hk%2F#toc-4
https://xz.aliyun.com/t/12994?time__1311=mqmhqIhiGKBKDsD7GG7Cbi%3DQDtkInuGD&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Ftab%2F1%3Fpage%3D3#toc-0

异常处理顺序

异常处理顺序:throw ->try中的catch
throw 函数会从当前函数找,然后往上找上个调用当前函数的函数,查看是否有函数有合适的catch处理模块,当前函数没有合适的catch处理模块就会把当前函数的栈帧给清除掉恢复到调用当前函数的函数,依次这样,知道找到合适的catch处理模块,然后再该模块下继续往后执行

eh_frame段的作用

#include <iostream>

void funcB() {
    throw std::runtime_error("Error in function B");
}

void funcA() {
    try {
        funcB();
    } catch (const std::exception& e) {
        std::cout << "Caught in A: " << e.what() << std::endl;
    }
}

int main() {
    try {
        funcA();
    } catch (...) {
        std::cout << "Caught in main" << std::endl;
    }
    return 0;
}

在这个例子中,funcB抛出了一个异常,funcA尝试捕获这个异常并处理它。如果funcA没有捕获到,异常会继续向上传递到main函数。

编译过程中的.eh_frame生成

当你编译这个程序时(比如使用g++编译器),编译器会生成额外的数据结构来支持异常处理流程,这些数据就储存在.eh_frame节中。.eh_frame包含了一系列被称为“异常表条目”(exception table entries)的信息,每个条目对应于可能抛出异常的函数(在这个例子中主要是funcB和含有try-catch块的函数)。

对于上面的代码,.eh_frame会记录下如下的关键信息:

  • 函数入口点:每个函数开始执行的位置。
  • 着陆垫(Landing Pad):异常发生后,控制流应该跳转到哪里去继续执行,通常是异常处理代码的起点。
  • 调用帧信息:如何恢复调用者的状态,包括如何调整堆栈指针、恢复寄存器等,以便正确地从异常发生点恢复到异常处理代码或继续执行。
  • 异常过滤信息:在某些高级用法中,还可以指定哪些类型的异常应该被哪个catch块处理。

运行时异常处理

当程序运行并且funcB抛出异常时,运行时系统会:

  1. 查找最近的未处理异常的catch块。
  2. 使用.eh_frame中的信息,计算出如何从当前执行点跳转到对应的catch块(即funcA中的catch或者如果没有被捕获则到main中的catch)。
  3. 执行必要的堆栈展开操作,恢复调用者的状态,保证异常处理代码能够在一个正确的上下文中执行。

堆栈展开

当运行时系统(如C++运行时库或操作系统的一部分)遇到一个未处理的异常时,它需要确定如何从当前执行点回退到能够妥善处理这个异常的代码位置,这一过程就叫做堆栈展开(stack unwinding)。堆栈展开涉及以下几个关键步骤:

  1. 识别异常处理程序:首先,系统需要知道应该去哪里寻找处理当前异常的代码。.eh_frame段包含了一个描述程序调用堆栈的结构化信息,使得运行时系统能够根据当前的调用序列找到最近的合适的catch块。

  2. 恢复调用者状态:在异常抛出点和异常处理器之间,可能有多个函数调用层次。堆栈展开的过程中,系统会逆序遍历这些调用层级,对每个调用帧(stack frame)执行必要的清理操作,比如:

    • 释放局部变量占用的堆栈空间。
    • 调用局部对象的析构函数,以确保资源被正确释放。
    • 重置CPU寄存器到调用该函数前的状态,以便正确返回到调用者上下文。
  3. 控制流转移:完成堆栈上各帧的清理后,运行时系统使用.eh_frame中记录的指令或地址信息,跳转到异常处理器(也就是catch块)开始执行。这个跳转确保了异常被正确处理,同时保持了程序状态的一致性和完整性。

简而言之,执行“必要的堆栈展开操作”意味着在异常传播路径上,系统要清理已不再需要的函数调用记录,恢复调用者环境,并最终将控制权传递给适当的异常处理逻辑,所有这些操作都是依据.eh_frame段提供的指令和数据来精确执行的。

简单劫持

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

class x {
    public:
    char buf[0x10];
    x(void) {
        printf("x:x() called\n");
    }
    ~x(void) {
        printf("x:~x() called\n");
    }
};

void test() {
    x a;
    int cnt = 0x100;
    size_t len = read(0,a.buf,cnt);
    if(len > 0x10) {
        throw "Buffer overflow";
    }
}

int main()
{
    try {
        test();
        throw 1;
    }
    catch(int x) {
        printf("Int: %d\n", x);
    }
    catch(const char* s) {
        printf("String: %s\n", s);
    }
    return 0;
}

rbp

throw函数最后会析构当前函数的变量,如果当前函数有合适的catch处理那么会进行catch处理,否则进行堆栈展开并跳转上一个函数的catch部分

假设溢出到test函数的rbp位置的值
在这里插入图片描述
__cxa_throw内最终执行到_Unwind_Resume后会将rbp置换到原来保存的rbp值也就是test函数的上一个函数的rbp值

在这里插入图片描述
跳转到main的异常处理catch后继续往后正常执行leave ret此时会将rsp变成rbp的值然后pop rbp然后ret,也就是ret会跳转到rbp+8的值的位置
在这里插入图片描述

ret

覆盖rbp和ret,这里注意rbp值要能够访问到,不然也会出错。

从抛出异常到开始执行 catch,包含两个过程:1. 从抛出异常的函数开始,对调用链上的函数逐个往前查找;2.如果没有找到 catch则把程序 abort,否则则记下 存在catch位置,再重新回到抛异常的函数开始清理调用链上的各个函数内部的局部变量并回溯,直到到达所在catch为止。

注意对调用链上的函数逐个往前找时查找位置和当前函数的返回地址有关,原来的返回地址是在try里面,下面正好有对应的catch

将返回地址设置为
在这里插入图片描述
最后依然成功到达了main的catch处理部分
在这里插入图片描述
如果在catch中呢
在这里插入图片描述
停到0x401276发现不可
在这里插入图片描述
0x0000000000401280试试,也不可
在这里插入图片描述
try catch中间这坨0x0000000000401262试试,_Unwind_RaiseException没有调到退出地方,好像可
在这里插入图片描述
_Unwind_Resume正常到main的catch处理部分,那可以
在这里插入图片描述
所以篡改返回地址大概就try部分和try和catch中间那坨可以正常到达返回地址所在的函数的catch部分

  • 而且_Unwind_RaiseException承担根据返回地址搜寻是否有合适catch的作用,没有最后会跳转到abort那部分
  • 当_Unwind_RaiseException寻找到有合适的才会析构当前函数对象然后进入_Unwind_Resume,最后跳到对应catch处理部分

chop

https://download.vusec.net/papers/chop_ndss23.pdf

静态编译
g++ -no-pie -g  -static llk.c -o llk
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

class x {
    public:
    char buf[0x10];
    x(void) {
        printf("x:x() called\n");
    }
    ~x(void) {
        printf("x:~x() called\n");
    }
};

void backdoor()
{
    system("/bin/sh");
}

void test() {
    x a;
    int cnt = 0x100;
    size_t len = read(0,a.buf,cnt);
    if(len > 0x10) {
        throw "Buffer overflow";
    }
}

int main()
{
    try {
        test();
        throw 1;
    }
    catch(int x) {
        printf("Int: %d\n", x);
    }
    catch(const char* s) {
        printf("String: %s\n", s);
    }
    return 0;
}

当程序抛出一个异常,而该异常没有被适当的catch块捕获时,控制权会转交给__cxa_call_unexpected函数

在ubuntu22.04上为__cxa_call_unexpected() ==> __cxa_call_unexpected.cold() ==>  (), 大略代码如下:

void __cxa_call_unexpected (void *exc_obj_in) {
 try { /* ... */ }
 catch (...) {
    __cxa_call_unexpected_cold(a1)
 }
}

void _cxa_call_unexpected_cold(void *a1) {
    void (*v2)(void); // r12
    void *retaddr; // [rsp+0h] [rbp+0h] BYREF
    /*...*/
    if (!check_exception_spec(&retaddr, ...)) {
        if (check_exception_spec(&retaddr, ... )) {
          /*...*/
          _cxa_throw();
        }
        __terminate(v2);
    }
}


void __terminate (void (*handler)()) throw () {
 /* ... */
 handler();
 std::abort();
}

在这里插入图片描述

需要控制局部变量进入_cxa_call_unexpected_cold()中__terminate的分支,防止中途再次抛出异常或是直接crash掉进程,terminate执行的函数指针是寄存器r12的值

利用到.eh_frame上的信息将栈上数据与寄存器做以联系,从而控制寄存器

readelf 是一个在类Unix系统上用于显示ELF格式可执行文件、目标文件、共享库等内部结构的工具。它是GNU Binary Utilities(binutils)套件的一部分。当你在命令行中使用 readelf 加上不同的选项和文件名,可以获取关于该文件的详细信息。

命令 readelf -wF file 的意义分解如下:

  • readelf: 这是命令本身,用于读取和解析ELF(Executable and Linkable Format,可执行与可链接格式)文件。

  • -w: 这个选项告诉 readelf 显示DWARF调试信息。DWARF是一种常用的调试文件格式,它包含了源代码级别的调试信息,如变量名、函数名、行号信息等,使得调试器能够提供源代码级的调试体验。

  • -F: 当与 -w 一起使用时,这个选项会让 readelf 显示DWARF信息中的框架信息(Frame Information)。框架信息对于理解函数调用堆栈、局部变量布局以及异常处理非常重要。

  • file: 这里替换为你要分析的具体文件名。它应该是你想要查看其DWARF调试信息中框架部分的 ELF 格式文件,比如一个可执行文件或者库。

readelf -wF file 命令的作用是展示指定ELF文件中的DWARF调试信息的框架部分

在这里插入图片描述

1. 异常发生时的堆栈保存

当程序中抛出一个异常时,首先异常处理机制会保存当前的执行上下文,包括程序计数器(PC)、栈指针(SP)以及其他寄存器的状态。这是通过硬件和操作系统共同完成的,确保了在异常处理完成后能够回到异常发生前的执行状态。

2. 查找.eh_frame信息

接着,异常处理机制会根据当前的PC(程序计数器)在.eh_frame节中查找对应的FDE(Frame Description Entry)。.eh_frame是ELF文件格式的一部分,存储了异常处理所需的信息,包括函数的堆栈帧布局和异常处理流程。

3. 解析FDE并恢复CFA

找到匹配的FDE后,异常处理机制会解析CFA(Canonical Frame Address)和各个寄存器的偏移量信息。CFA是理解当前堆栈帧布局的关键,它通常是指向当前栈帧底部的某个参考点,比如栈指针减去一定偏移量。通过FDE中描述的规则,异常处理程序知道如何从CFA计算得到各个寄存器的值。

4. 恢复寄存器

根据FDE中的规则,异常处理机制会从当前的堆栈中恢复寄存器的值。例如,如果规则指出rbp寄存器的值在CFA之下16字节处,异常处理程序就会从当前栈顶指针减去16字节的位置读取rbp的值并将其恢复到寄存器中。这个过程会重复进行,直到所有需要恢复的寄存器都按照规则恢复完毕。

5. 堆栈展开

在寄存器恢复之后,异常处理机制还需要进行堆栈展开,即逐步弹出函数调用栈中的帧,直到找到能够处理当前异常的catch块。这个过程同样依赖于.eh_frame中的信息,通过迭代地应用FDE中的规则来逐步恢复调用链上各函数的堆栈状态。

6. 转向异常处理逻辑

最后,当异常被正确地传递给一个catch块时,控制权会转移给catch块中的代码,程序可以从异常发生点之后继续执行,此时寄存器和堆栈已经恢复到一个已知的、安全的状态。

先忙awd了以后补

待解决

  • 参考中说将ret设置为能够在异常中恢复寄存器的地址,但发现会卡在,栈上的值都设置成能访问的了,还是不行
    在这里插入图片描述

可能方法

  • 用ubuntu22.04试试,和参考的环境一样也许能成功
  • maybe要求这个ret设置为能够在异常中恢复寄存器的地址 也需要为在try中的地址?

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

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

相关文章

LeetCode刷题之HOT100之二叉树的遍历

2024/6/14 这几天总是下雨&#xff0c;天气预报上面显示这个月都要持续下雨&#xff0c;下雨天了怎么办&#xff1f;我好想你&#xff0c;不敢打给你&#xff0c;我找不到原因。说着说着唱起来了哈哈&#xff01;Anyway&#xff0c;昨天晚上打开了《涅朵奇卡一个女人的一生》&a…

Vue3:解决在main.ts 中调用自定义的js文件会报错的问题

案例&#xff1a;Vue3 &#xff0c;使用的是main.ts &#xff0c;在main.ts 中调用自定义的ruoComment.js文件会报错&#xff0c; 页面报错&#xff1a; main.ts文件引用报错&#xff1a; 解决报错&#xff1a;找到tsconfig.json文件 加上如下代码&#xff1a;即可解决问题 &q…

IDC最新报告,7大维度11家大模型厂商比拼,唯一全优是谁?

如果考试题太简单&#xff0c;学渣也能拿一百昏。在 AI 圈&#xff0c;我们应该拿怎样的「试卷」来检验一直处于流量 C 位的大模型的真实水平&#xff1f;是高考题吗&#xff1f;当然不是&#xff01; 也有些人认为&#xff0c;在各种 Benchmark 榜单上&#xff0c;谁排第一谁…

ai 人工智能免费网站免费生成图片生成ppt

豆包 Kimi.ai - 帮你看更大的世界 生成ppt 讯飞智文 - AI在线生成PPT、Word 大家如有其它免费的欢迎推荐!!!

动力学仿真平台:让模型配置与仿真测试更高效!

背景概述 动力学仿真平台是一种基于计算机技术的模拟工具&#xff0c;旨在模拟和分析物理系统中的动力学行为。通过建立数学模型&#xff0c;并借助高效的数值计算方法来模拟复杂系统的运动规律&#xff0c;为科研、设计、工程等领域提供重要的决策支持。动力学仿真平台的重要性…

图像算法之镜头畸变

桶形畸变&#xff08;Barrel Distortion&#xff09;&#xff1a; 桶形畸变是一种常见于广角镜头的畸变类型。在桶形畸变中&#xff0c;图像的中心区域被向外拉伸&#xff0c;使得直线在图像边缘部分显得向内弯曲&#xff0c;看起来像一个桶。这种畸变之所以发生&#xff0c;是…

Linux操作系统学习路线

本文来自Qwen2大模型&#xff1a; Linux操作系统的全面学习是一个渐进的过程&#xff0c;涵盖从基础知识到高级特性的多个阶段。以下是一份详细的Linux操作系统学习路线图&#xff0c;包括各个阶段的学习目标、建议的学习资源和实践步骤。 1. Linux 基础知识与安装 学习目标&a…

CD工具awx之清单Inventory,管理应用与主机的多对多关系

一、什么是清单 它决定的是一个应用部署到哪些目标机&#xff0c;清单管理的是应用&#xff08;组&#xff09;关联了哪些主机&#xff08;目标机&#xff09;。 1、新建清单 2、新建组 3、关联主机 新增主机或关联已有的主机 新主机 现有主机 服务关联主机完成&#xf…

ElementPlus国际化(将组件的默认语言改为中文)

文章目录 1. Element-plus的默认语言2. 编辑 main.js 文件3. 效果&#xff08;以分页条组件为例&#xff09; 1. Element-plus的默认语言 Element-plus的默认语言是英语&#xff0c;可修改为其它语言 2. 编辑 main.js 文件 import {createApp} from vue import ElementPlus …

deepin V23 RC2 正式发布!

deepin 是一款基于 Linux 的开源桌面操作系统&#xff0c;今天 deepin V23 RC2 正式发布&#xff0c;欢迎体验与反馈&#xff01;感谢每一位 deepiner 提供想法与建议&#xff0c;让我们一起为打造美观易用、安全可靠的开源操作系统而努力&#xff01; 【功能新增与优化】 新增…

电脑自带录屏在哪?电脑录屏,4个详细方法

在现代社会中&#xff0c;越来越多的人需要在电脑上录制视频&#xff0c;比如录制游戏操作、制作教学视频、演示文稿等等。因此&#xff0c;电脑录屏成为了一项非常重要的功能。那么电脑自带录屏在哪&#xff1f;本文将带领大家看看可以使用哪些方法进行录屏。 录屏方法一&…

CC攻击的有效应对方案

随着互联网的发展&#xff0c;网络安全问题愈发突出。CC攻击&#xff08;Challenge Collapsar Attack&#xff09;&#xff0c;一种针对Web应用程序的分布式拒绝服务&#xff08;DDoS&#xff09;攻击方式&#xff0c;已经成为许多网络管理员和网站拥有者不得不面对的重大挑战。…

什么?项目经理也算经理?

今天偶然看到一个有意思的问题&#xff1a;“如何破解项目经理的无权、无利、有责的现状”&#xff1f; 乍看有点费解&#xff0c;细想还挺有意思&#xff0c;这不禁引发了我的思考&#xff0c;项目经理到底算不算经理&#xff1f; 从管理学的角度来看&#xff0c;根据亨利法约…

电信网关配置管理系统 del_file.php 前台RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

笔记本电脑怎么连接无线网WiFi?4个连接方法分享!

“我新买了一台笔记本电脑&#xff0c;现在不知道怎么操作才能连接无线网。有朋友知道应该怎么操作吗&#xff1f;希望大家给我分享一下简单的方法。” 在数字化飞速发展的今天&#xff0c;笔记本电脑作为我们日常生活与工作中不可或缺的工具&#xff0c;其无线连接功能的重要性…

五分钟看完WWDC24

大家好&#xff0c;我是小编阿文。欢迎您关注我们&#xff0c;经常分享有关Android出海&#xff0c;iOS出海&#xff0c;App市场政策实时更新&#xff0c;互金市场投放策略&#xff0c;最新互金新闻资讯等文章&#xff0c;期待与您共航世界之海。 北京时间6月11日凌晨1点&…

智能化六面体大米装袋机:如何助力提升包装效率与质量

在快节奏的现代社会&#xff0c;高效、精准的包装设备对于提升大米产业的生产效率与产品质量至关重要。近年来&#xff0c;随着科技的不断进步&#xff0c;智能化六面体大米装袋机凭借其较好的性能和便捷的操作&#xff0c;逐渐成为大米加工企业的新宠。星派将深入探讨智能化六…

管理十大定律:深度解析与实际应用

在复杂多变的企业管理环境中&#xff0c;掌握并运用一些基本的定律和规律&#xff0c;对于提升管理效率、优化资源配置具有至关重要的作用。 1、马太效应 定律解析&#xff1a;马太效应描述了资源分配中的一种累积优势现象&#xff0c;即强者愈强&#xff0c;弱者愈弱。这源…

化学品危险性分类鉴定报告 危化品危险性分类

一、化学品危险性分类报告&#xff1a; 按照国务院令 第591号 《危险化学品安全管理条例》、原十部委公告 2015年 第5号 《危险化学品目录&#xff08;2015版&#xff09;》、原安监总局令 第60号《化学品物理危险性鉴定与分类管理办法》和原安监总局令 第53号《危险化学品登记…

KTH4603 3D Hall传感器在强磁入侵检测中的应用

背景介绍 电子系统一直面临强磁干扰的威胁&#xff0c;保护这些设备免受强磁干扰成为一个重要课题。非法者通过施加强磁意图篡改或干扰它们&#xff0c;窃取产品或服务。强磁场可以对电子设备产生严重的影响&#xff0c;包括但不限于&#xff1a;数据损坏、功能故障、安全隐患…