CTF-pwn-虚拟化-qemu前置知识

2024-06-22 01:36

本文主要是介绍CTF-pwn-虚拟化-qemu前置知识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 参考
  • 地址相关
  • 交互相关
  • 配置相关
  • 调试
  • 待完善(以后做题用到啥再加吧)

参考

https://xz.aliyun.com/t/6562?time__1311=n4%2bxnD0DRDBAi=GkDgiDlhjmYh2xuCllx7whD&alichlgref=https://www.bing.com/#toc-3

地址相关

每个qemu虚拟机都是宿主机上的一个进程,在进程中用mmap分配出大小为0x40000000字节的宿主机的虚拟内存来作为虚拟机的物理内存

GVA:guest virtual address(虚拟机中的虚拟地址)
GPA:guest physical address(虚拟机中的物理地址)
HVA:host virtual address(宿主机中的虚拟地址)
HPA: host physical address(宿主机中的物理地址)

GVA通过客户机的页表得到GPA,GPA实际是由宿主机进程mmap出来的空间内的偏移。再加上起始地址就是HVA(mmap分配出相应虚拟机申请大小的内存,用于给该虚拟机当作物理内存)

  1. 设备可以申请两类空间,memory mapped I/O(MMIO)和port mapped I/O(PMIO),并在配置空间中用Base Address Registers(BAR)来标记内存地址信息
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <inttypes.h>#define PAGE_SHIFT  12
#define PAGE_SIZE   (1 << PAGE_SHIFT)
#define PFN_PRESENT (1ull << 63)
#define PFN_PFN     ((1ull << 55) - 1)int fd;uint32_t page_offset(uint32_t addr)
{return addr & ((1 << PAGE_SHIFT) - 1);//虚拟地址addr在其所在页面内的偏移量
}uint64_t gva_to_gfn(void *addr)
{uint64_t pme, gfn;size_t offset;offset = ((uintptr_t)addr >> 9) & ~7;//页表条目相对于文件开始的偏移量(GFN, Guest Physical Frame Number)lseek(fd, offset, SEEK_SET);//移动文件指针到计算出的偏移量处,准备读取PTE。read(fd, &pme, 8);  //从文件中读取8字节到pme变量即物理块起始地址if (!(pme & PFN_PRESENT))return -1;gfn = pme & PFN_PFN;return gfn;
}uint64_t gva_to_gpa(void *addr)
{uint64_t gfn = gva_to_gfn(addr);assert(gfn != -1);return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr);
}int main()
{uint8_t *ptr;uint64_t ptr_mem;// uint64_t ptr_malloc;fd = open("/proc/self/pagemap", O_RDONLY);if (fd < 0) {perror("open");exit(1);}ptr = malloc(256);strcpy(ptr, "Where am I?");printf("%s\n", ptr);ptr_mem = gva_to_gpa(ptr);printf("Your physical address is at 0x%"PRIx64"\n", ptr_mem);// ptr_malloc = gva_to_gpa(&malloc);// printf("malloc physical address 0x%"PRIx64" \n",ptr_malloc);getchar();return 0;
}

在这里插入图片描述
gdb attach后vmmap可以查看到启动脚本中的-M指定的分配大小

在这里插入图片描述在这里插入图片描述

交互相关

每个PCI设备有一个总线号、一个设备号、一个功能标识,存在PCI域,PCI域最多可以承载256条总线, 每条总线最多可以有32个设备,每个设备最多可以有8个功能

lspci 可以查看设备所在的域、总线号、设备号、功能号,不同版本lspci 显示的内容不一样

其中对于形如0000:00:03.0的数据,0000是域,00是总线号,03是设备号,0是功能号
在这里插入图片描述
resource中的pmio端口和mmio起始地址是固定的
mmio:将设置的寄存器映射到端口,访问端口来访问寄存器
pmio:将设置的寄存器映射到内存, 访问内存来访问寄存器

  • hexdump /sys/devices/pci0000:00/0000:00:03.0/config查看配置信息如deviceid和vendorid
  • 访问memory mapped I/O内存:打开获取fd后用mmap映射内存地址,直接操作内存
int mmio_fd = open("/sys/devices/pci0000:00/0000:00:04.0/resource0", O_RDWR | O_SYNC);
mmio_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
  • 访问port mapped I/O内存:申请访问端口权限后用in、out访问
iopl(3);// iopl(3) 表示打开对全部IO端口的访问权限
inb(port); //从端口读一个字节
outb(val,port); //往端口写一个字节val

设备会注册自己的MMIO和PMIO读写函数,当检测到访问其所在的内存或端口时调用注册的读写函数,实现对设备内存的读写功能

当对设备其所在的内存访问时,会调用注册的读mmio函数d3dev_mmio_read,读的位置是基地址+0x128,是4字节。被d3dev_mmio_read识别为了rsi为0x128(偏移),rdx为4

在这里插入图片描述
在这里插入图片描述
当对设备其所在的内存写时,会调用注册的写mmio函数d3dev_mmio_write
在这里插入图片描述

#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/io.h>unsigned char* mmio_mem;void die(const char* msg)
{perror(msg);exit(-1);
}void mmio_write(uint32_t addr, uint32_t value)
{*((uint32_t*)(mmio_mem + addr)) = value;
}uint32_t mmio_read(uint32_t addr)
{return *((uint32_t*)(mmio_mem + addr));
}int main(int argc, char *argv[])
{// Open and map I/O memory for the strng deviceint mmio_fd = open("/sys/devices/pci0000:00/0000:00:03.0/resource0", O_RDWR | O_SYNC);//O_SYNC标志表示同步I/O操作,确保对文件的写操作在返回前完成if (mmio_fd == -1)die("mmio_fd open failed");mmio_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);//PROT_READ | PROT_WRITE:指定映射区域的访问权限,这里允许读写。//MAP_SHARED:映射类型,共享映射意味着对映射区域的修改会反映到设备上,其他映射同一资源的进程也能看到修改。//mmio_fd:之前通过open获得的文件描述符。//0:文件偏移量,从资源的起始位置开始映射。if (mmio_mem == MAP_FAILED)die("mmap mmio_mem failed");printf("mmio_mem @ %p\n", mmio_mem);mmio_read(0x128);mmio_write(0x128, 1337);mmio_read(0x128);}

在这里插入图片描述
可以发现rsi会被设置成偏移
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/io.h>void die(const char* msg)
{perror(msg);exit(-1);
}uint32_t pmio_base=0xc040;uint32_t pmio_write(uint32_t addr, uint32_t value)
{outl(value,addr);
}uint32_t pmio_read(uint32_t addr)
{return (uint32_t)inl(addr);
}int main(int argc, char *argv[])
{if (iopl(3) !=0 )die("I/O permission is not enough");pmio_read(pmio_base+4);pmio_write(pmio_base+4,1);pmio_read(pmio_base+4);}
  • qemu中执行其中的程序时,当涉及到设备读写此时进行的操作会是qemu进程执行的,不是虚拟中的,就是对qemu进程上的虚拟地址相关进行操作,不是mmap出来作为宿主机的那部分(就和平常用户态一样了)
  • 注册的相关读写函数中的addr是偏移,mmio范围是0x800,pmio是0x20

配置相关

PCI设备有其配置空间来保存设备信息,头部最开始的数据为Device id和Vendor id

在初始化设备时会初始化四个比较重要的结构体:TypeInfo -> TypeImpl -> ObjectClass -> Object,每个 Object对应一个具体的device,其构造函数在qemu启动用-device参数加载设备时调用

设备读写操作函数的第一个参数是这个Object类的指针

调试

打包exp到文件系统

gcc -static exp.c -o   exp
find . | cpio -o --format=newc > ../rootfs.img

启动qemu

./launch.sh
touch .gdbinit
往里面写入断点
b*d3dev_pmio_write
b*d3dev_pmio_read
b*d3dev_mmio_write
b*d3dev_mmio_read
ps -ef | grep qemu
一般是最下面的那个进程
sudo gdb attach -p 进程号

在qemu中

./exp

此时gdb会断在断点上,然后开始调试

成功attach之后即可下断点调试,开启了pie保护,且没有符号表可以用pwndbg的$rebase()根据ida中的地址确定进程中的真实地址

待完善(以后做题用到啥再加吧)

这篇关于CTF-pwn-虚拟化-qemu前置知识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082914

相关文章

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库

dr 航迹推算 知识介绍

DR(Dead Reckoning)航迹推算是一种在航海、航空、车辆导航等领域中广泛使用的技术,用于估算物体的位置。DR航迹推算主要通过已知的初始位置和运动参数(如速度、方向)来预测物体的当前位置。以下是 DR 航迹推算的详细知识介绍: 1. 基本概念 Dead Reckoning(DR): 定义:通过利用已知的当前位置、速度、方向和时间间隔,计算物体在下一时刻的位置。应用:用于导航和定位,

【虚拟化】AIO主机安装PVE8,配置网络,安装win11(virtio,qcow2,scsi,oobe,adk)

【虚拟化】AIO主机安装PVE8,配置网络,安装win11(virtio,qcow2,scsi,oobe,adk) 文章目录 1、ESXI vs PVE,AIO主机系统二选一2、PVE网络配置(DNS,换源,网卡,https,概览)3、win11虚拟化配置(virtio,raw,qcow2)附,域名解析,rocky9.4,黑群晖 1、ESXI vs PVE,AIO主机系统二选

【CTF Web】BUUCTF Upload-Labs-Linux Pass-13 Writeup(文件上传+PHP+文件包含漏洞+PNG图片马)

Upload-Labs-Linux 1 点击部署靶机。 简介 upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。 注意 1.每一关没有固定的通关方法,大家不要自限思维! 2.本项目提供的writeup只是起一个参考作用,希望大家可以分享出自己的通关思路

Linux 云计算底层技术之一文读懂 Qemu 架构

Qemu 架构概览 Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。 正因为 Qemu 是纯软件实现的,所有的指令都要经 Qemu 过一手,性能非常低,所以,在生产环境中,大多数的做法都是配合 KVM 来完成

【H2O2|全栈】Markdown | Md 笔记到底如何使用?【前端 · HTML前置知识】

Markdown的一些杂谈 目录 Markdown的一些杂谈 前言 准备工作 认识.Md文件 为什么使用Md? 怎么使用Md? ​编辑 怎么看别人给我的Md文件? Md文件命令 切换模式 粗体、倾斜、下划线、删除线和荧光标记 分级标题 水平线 引用 无序和有序列表 ​编辑 任务清单 插入链接和图片 内嵌代码和代码块 表格 公式 其他 源代码 预

【QNX+Android虚拟化方案】120 - Android 侧 USB2.0 插拔过程

【QNX+Android虚拟化方案】120 - Android 侧 USB2.0 插拔过程 基于原生纯净代码,自学总结 纯技术分享,不会也不敢涉项目、不泄密、不传播代码文档!!! 本文禁止转载分享 !!! 汇总链接:《【QNX+Android虚拟化方案】00 - 系列文章链接汇总》 本文链接:《【QNX+Android虚拟化方案】120 - Android 侧 USB2.0