以下步骤是我一步步尝试,经历了多种报错,解决之后摸索出来的
参考:
KVM-VMI项目的官方文档:https://kvm-vmi.github.io/kvm-vmi/master/setup.html
中科院DAMS实验室的文档:https://dams.net.cn/book/2025/lab6/(里面有配套的虚拟化安全有关的实验,适合刚入门的学习)
我学习是以中科院DAMS实验室的文档为主,KVM-VMI项目为辅
注:实验过程中一定要留好快照,报错的时候,你把环境搅得一塌糊涂的时候,你会发现太重要了
在学习虚拟化安全的过程中我将会分享我自己的学习笔记(包括虚拟化安全知识的基础学习、实验过程、深度理解计算机系统(CSAPP)这本书的学习)
实验6所在的环境:

KVM-VMI项目克隆的完整步骤:https://blog.csdn.net/2201_76139143/article/details/159314344?spm=1001.2014.3001.5502
在kvm-vmi目录下执行
(1)切换到kvmi-v7分支
检查本地+远程所有分支
git branch -a

切换分支
# 切换到 kvmi-v7 分支(本地无该分支时会自动创建并关联远程)
git checkout kvmi-v7

查看是否切换成功
git branch

更新子模块(有的时候一次不成功,可以多次执行,不会在下载已经下载完成的了)
# 初始化+更新所有递归子模块(适配 kvmi-v7 分支的版本)
git submodule update --init --recursive
无输出,代表模块是最新版本,无需进行额外操作
会出现qemu下面的roms/vgabios模块的报错问题,直接更改qemu目录下.gitmodules文件中这个模块的地址为https://github.com/qemu/vgabios.git,再执行git submodule sync,再重新递归更新子模块就成功了
1、安装kvm(整个过程在kvm目录下执行)
(1)安装所需依赖
sudo apt-get install bc fakeroot flex bison libelf-dev libssl-dev dwarves
(2)
cd kvm
# 先给权限,避免因为权限报错
chmod +x scripts/*.sh
chmod +x scripts/*/*.sh
make distclean # 清理之前的编译残留,避免配置冲突
cp /boot/config-$(uname -r) .config
make olddefconfig # 用当前内核配置为基础,将新选项设为默认值
# 先给权限
# 给 config 工具添加执行权限(核心修复)
chmod +x scripts/config
./scripts/config --enable KVM
./scripts/config --enable KVM_INTEL
./scripts/config --enable KVM_AMD
./scripts/config --enable KVM_INTROSPECTION
./scripts/config --disable TRANSPARENT_HUGEPAGE
./scripts/config --enable REMOTE_MAPPING
./scripts/config --disable SYSTEM_TRUSTED_KEYS
./scripts/config --disable SYSTEM_REVOCATION_KEYS
# 这个是给内核名称加kvmi后缀的,只有setup中提到了(我没执行)
./scripts/config --set-str CONFIG_LOCALVERSION -kvmi
# 这两个只有setup中提到了,unbuntu 22.04兼容性,我的是20.04不需要
./scripts/config --enable PREEMPT
./scripts/config --disable NET_VENDOR_NETRONOME
(3)编译打包
make -j$(nproc) bindeb-pkg
生成 Debian 格式的内核包,会在上级目录生成 .deb 文件
中间有交互的按回车就行

(4)
sudo dpkg -i ../linux-image-5.4.24+_5.4.24*deb
注意:文件名可能因编译环境略有不同,可用 ls ../linux-image*.deb 确认实际文件名后再安装

因为我没有加-kvmi,所以要将-kvmi去掉(加了可以很直观的直到哪一个是自己编译的虚拟机内核)
(5)
重启(要选择自己编译的内核),uname -a,能得到 5.4.24+ (kvmi v7)

虽然没有显示kvmi v7 但是我检查了自己更新子模块的时候是在kvm-vmi目录下执行的,当时处理qemu模块,其它模块都同步成功了。后来qemu也同步成功了,所以没有什么问题
2、安装qemu
(1)关闭apparmor
sudo service apparmor stop
(2)安装依赖
sudo apt-get install libpixman-1-dev pkg-config zlib1g-dev libglib2.0-dev dh-autoreconf libspice-server-dev
(3)配置、建立和安装qemu
cd qemu
./configure --target-list=x86_64-softmmu --enable-spice --prefix=/usr/local --python=/usr/bin/python3
# 我的python路径找不到,所以我多家了一个python路径
make -j4
sudo make install
(4)验证
/usr/local/bin/qemu-system-x86_64 --version

这个版本和官方给的版本一致
3、准备一个域
The Virtual Machine should be available in libvirt。就是执行 virsh list --all 的时候可以看到自己的虚拟机。
(1)使用virt-manager创建虚拟机
① 安装依赖
sudo apt update
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
② 加入libvirt组
sudo usermod -aG libvirt $USER # 相当于给你的账号 "登记" 到 libvirt 权限组里,从此你的账号永久拥有管理虚拟机的权限资格
newgrp libvirt # 相当于 "立即激活" 这个权限资格,让当前打开的终端马上用上 libvirt 组的权限
# 永久生效,重启之后无需重复执行
# 取消这两条指令
sudo gpasswd -d $USER libvirt
newgrp
关机重启一次
③ 准备系统iso(具体步骤在创建并启动Windows虚拟机部分)
④ 启动virt-manager,利用其安装Windows虚拟机(具体步骤在利用virt-manager创建虚拟机部分)
virt-manager
安装之后关机

(2)配置xml文件(给虚拟机加了一个监控接口,使外部的设备可以实时调试、监控虚拟机)
sudo virsh edit win7-i686
出现问题1:

这个问题的解决办法在下面(配置xml文件时libvirt没有执行/usr/local/bin/qemu-system-x86_64的权限问题的分析与解决)
保存退出
(3)验证配置
# 检查 XML 配置是否合法
sudo virsh define /etc/libvirt/qemu/你的Win7虚拟机名.xml

启动虚拟机(验证配置无错误)
sudo virsh start win7-i686
出现问题2:

这是为什么报错的原因:
还有一个原因:就是qemu的版本太老了不支持USB重定向
所以在安装配置虚拟机的时候要选择移除(如果安装好了也没关系,直接利用virt-manager图形界面移除就好):
选中 USB Redirector 1 → 点
Remove选中 USB Redirector 2 → 点
Remove
出现问题3:

自己编译的 QEMU 版本太新 / 太旧,不支持 libvirt 自动给你选的机器型号 pc-i440fx-focal
可以使用以下命令查看qemu支持的机器型号
/usr/local/bin/qemu-system-x86_64 -M help
原来xml配置为:
<os>
<type arch='i686' machine='pc-i440fx-focal'>hvm</type>
<boot dev='hd'/>
</os>
改为:
<os>
<type arch='x86_64' machine='pc-i440fx-2.12'>hvm</type>
<boot dev='hd'/>
</os>
出现问题4:

自己编译的 QEMU 关闭了 seccomp 安全沙箱功能,但 libvirt 仍然强制要求开启它 → 冲突 → 启动失败。
更改qemu.conf文件,关闭libvirt的沙箱功能
sudo nano /etc/libvirt/qemu.conf
将原来的 1改为0,并去掉# seccomp_sandbox = 0
# 查看虚拟机状态
sudo virsh domstate 你的Win7虚拟机名 # 显示 running 即为正常

正常安全关机: sudo virsh shutdown win7-i686 这个需要等一会,因为关机需要一个过程
强制关机: sudo virsh destroy win7-i686
重启虚拟机: sudo virsh reboot win7-i686
4、安装libkvmi
cd kvm-vmi/libkvmi
./bootstrap # 准备编译环境,生成 configure
./configure # 检查环境,生成编译说明书
make
sudo make install
之后启动虚拟机win7-i686,测试运行
cd libkvmi/examples
./hookguest-libkvmi /tmp/introspector
成功!
5、安装libvmi
(1)安装依赖
sudo apt-get install build-essential gcc libtool cmake pkg-config check libglib2.0-dev libvirt-dev flex bison libjson-c-dev
(2)编译安装
cd kvm-vmi/libvmi
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DENABLE_KVM=ON -DENABLE_XEN=OFF -DENABLE_BAREFLANK=OFF
make -j2
sudo make install
JSON profiles
TO use all the features of LibVMI, you need a Rekall/Volatility profile.
(1)
先将 kvm-vmi/libvmi/etc/libvmi-example.conf 复制到 /etc/libvmi.conf
sudo cp ~/Desktop/v/kvm-vmi/libvmi/etc/libvmi-example.conf /etc/libvmi.conf
然后将虚拟机名字改为其中对应的名字。这里我们使用 Windows7 虚拟机(32位),所以就将虚拟机名字改为 win7-i686,与配置文件对应(修改配置文件使其与虚拟机名字对应亦可):
sudo nano /etc/libvmi.conf

运行 LibVMI 自带工具,提取目标 Windows 虚拟机的内核的GUID和PE_HEADER:(这个文件在libvmi/build/examples目录下)
examples/vmi-win-guid name win7-i686 /tmp/introspector
记录输出中的 Kernel filename和 PDB GUID。
Windows Kernel found @ 0x3c16000
Version: 32-bit Windows 7
PE GUID: 4ce78a06404000
PDB GUID: 00625d7d36754cbeba4533ba9a0f3fe22
Kernel filename: ntkrnlmp.pdb
Multi-processor without PAE
Signature: 17744.
Machine: 332.
# of sections: 22.
# of symbols: 0.
Timestamp: 1290242566.
Characteristics: 258.
Optional header size: 224.
Optional header type: 0x10b
Section 1: .text
Section 2: _PAGELK
Section 3: POOLMI
Section 4: POOLCODE
Section 5: .data
Section 6: ALMOSTRO
Section 7: SPINLOCK
Section 8: PAGE
Section 9: PAGELK
Section 10: PAGEKD
Section 11: PAGEVRFY
Section 12: PAGEHDLS
Section 13: PAGEBGFX
Section 14: PAGEVRFB
Section 15: .edata
Section 16: PAGEDATA
Section 17: PAGEKDD
Section 18: PAGEVRFC
Section 19: PAGEVRFD
Section 20: INIT
Section 21: .rsrc
Section 22: .reloc
拦截并显示CR3事件
examples/cr3-event-example win7-i686 /tmp/introspector
Waiting for events...
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
CR3 write happened: Value=0x7fc7c000
CR3 write happened: Value=0x185000
...
打印虚拟机中运行的进程列表
examples/vmi-process-list -n win7-i686 -s /tmp/introspector
LibVMI Suggestion: set win_ntoskrnl=0x3c16000 in libvmi.conf for faster startup.
LibVMI Suggestion: set win_kdbg=0x121c28 in libvmi.conf for faster startup.
LibVMI Suggestion: set win_kdvb=0x83d37c28 in libvmi.conf for faster startup.
Process listing for VM win7-i686 (id=1)
[ 4] System (struct addr:85c3bd40)
[ 264] smss.exe (struct addr:86cfac48)
[ 348] csrss.exe (struct addr:874b0570)
[ 396] wininit.exe (struct addr:87149200)
[ 404] csrss.exe (struct addr:874116a0)
[ 432] winlogon.exe (struct addr:85cae4b0)
[ 484] services.exe (struct addr:875c5318)
[ 500] lsass.exe (struct addr:875cd030)
[ 508] lsm.exe (struct addr:875cea78)
[ 612] svchost.exe (struct addr:8766ad40)
[ 684] svchost.exe (struct addr:86e32620)
[ 768] svchost.exe (struct addr:876af030)
[ 816] svchost.exe (struct addr:876c4c88)
[ 840] svchost.exe (struct addr:876d2ac0)
[ 996] svchost.exe (struct addr:876fe8b8)
[ 1084] svchost.exe (struct addr:87812498)
[ 1220] spoolsv.exe (struct addr:86dde030)
[ 1268] svchost.exe (struct addr:8786b898)
[ 1652] taskhost.exe (struct addr:875698e0)
[ 1812] dwm.exe (struct addr:8656a360)
[ 1828] explorer.exe (struct addr:87953828)
[ 1024] SearchIndexer. (struct addr:86cf3630)
[ 1156] svchost.exe (struct addr:879d5030)
[ 1932] sppsvc.exe (struct addr:8758b3b0)
[ 544] svchost.exe (struct addr:86dfa820)
(2)用 Volatility3 生成 JSON 配置(先不配置)
git clone https://github.com/volatilityfoundation/volatility3
cd volatility3
virtualenv -p python3 venv
source venv/bin/activate
(venv) $ pip install -e .
(venv) $ python volatility/framework/symbols/windows/pdbconv.py -o profile.json -p <Kernel filename> -g <PDB GUID>
Debug output(先不进行,这里我还未尝试)
如果你需要调试 LibVMI 运行时行为,可以通过 CMake 开启调试选项,并用环境变量控制输出:
(1)编译时开启调试选项
cd build
cmake .. -DVMI_DEBUG='(VMI_DEBUG_KVM | VMI_DEBUG_DRIVER)'
make
sudo make install
VMI_DEBUG_KVM:开启 KVM 相关调试日志VMI_DEBUG_DRIVER:开启驱动层调试日志- 可在
libvmi/debug.h中查看所有可用调试常量
(2)运行时启用调试输出(可选)
通过环境变量 LIBVMI_DEBUG=1
LIBVMI_DEBUG=1 ./build/examples/vmi-process-list -n winxp -j /etc/libvmi/winxp-profile.json
-n winxp:目标虚拟机名称-j /etc/libvmi/winxp-profile.json:指定之前生成的 JSON 配置文件
创建并启动Windows虚拟机:
下载Windows镜像
复制链接
ed2k://|file|cn_windows_7_professional_with_sp1_x86_dvd_622569.iso|2651877376|56C4B513A6109715CD2BEBFBA80370A0|/
在迅雷里下载,下载之后哈希校验(直接在Windows终端校验)
Get-FileHash -Path .\cn_windows_7_professional_with_sp1_x86_dvd_622569.iso -Algorithm SHA1
以下过程我没有进行,是在另一个实验中进行的
1、创建磁盘文件
qemu-img create -f qcow2 win7.img 25G
2、启动虚拟机
qemu-system-x86_64 -cpu host -smp 2 -m 2048 --enable-kvm -hda win7.img -cdrom win7.iso -vga virtio -boot order=d
3、借用gvncview连接虚拟机
gvncviewer 127.0.0.1::5900
利用virt-manager创建虚拟机
新建虚拟机

选择iso镜像

内存:

外存:

磁盘总线:

网卡:

添加第二个 CDROM 光驱:

放 VirtIO 驱动镜像,在安装时用来加载磁盘 / 网卡驱动
显示器:

安装


现在安装












右键点击 以太网控制器 → 选择「更新驱动程序软件」 → 「浏览计算机以查找驱动程序软件」

先安装「PCI 简易通讯控制器」→ 再安装「PCI 设备」
配置xml文件时libvirt没有执行/usr/local/bin/qemu-system-x86_64的权限问题的分析与解决
分析:
意思是libvirt没有执行/usr/local/bin/qemu-system-x86_64的权限
另外
-rwxr-xr-x 1 root root 13918384 3月 22 11:34 /usr/local/bin/qemu-system-x86_64表示其它用户和所属组都没有写的权限,文件所属组和所属用户都是root
=?为什么libvirt不能执行?
查看系统所有用户cat passwd,发现有libvirt-qemu用户,但是没有qemu用户
查看libvirt的配置文件, 发现默认示例配置是 user = "qemu" ,不用担心这个配置完全不生效,因为被注释了

# 查看 libvirt QEMU 驱动的默认配置
sudo virsh capabilities | grep -A5 "qemu" | grep "user"
没有输出
改变libvirt的配置也不行(将用户和组前的root #去掉不行、添加libvirt-qemu也不行、qemu用户也试了也不行)
sudo nano /etc/libvirt/qemu.conf # 编辑
sudo systemctl restart libvirtd # 重启使生效

也不行:

libvirt-qemu有权限执行:

软链接也没有用,证明不是路径的问题,是文件本身的问题 可是文件本身也没问题(有权限+没有隐形标记)
我关闭sudo service apparmor stop之后还是不能执行?确认已关闭apparmor(sudo service apparmor status)
我也查看了文件本身没有 AppArmor/SELinux 隐形标记
**解决办法1:**将qemu-system-x86_64名字和路径改为和qemu-system-i686一致,qemu-system-i686备份,解决了权限的问题(发现这个也可以解决问题,最后和最终方法的走向是一致的)
步骤 1:备份系统默认 QEMU(关键,可回滚)
sudo mv /usr/bin/qemu-system-i386 /usr/bin/qemu-system-i386.bak步骤 2:替换为你的 KVM-VMI 版 QEMU
# 复制自定义 QEMU 到系统默认路径(改名适配) sudo cp /usr/local/bin/qemu-system-x86_64 /usr/bin/qemu-system-i386 # 重置权限(确保 libvirt 能执行) sudo chmod 755 /usr/bin/qemu-system-i386 sudo chown root:root /usr/bin/qemu-system-i386 # 验证替换成功(显示你的 KVM-VMI 版本) /usr/bin/qemu-system-i386 --version步骤 3:修改 XML
virsh edit win7-i686步骤 4:启动虚拟机验证(出现问题)
virsh start win7-i686但是又会出现新的问题
意思是:当前版本的 QEMU(你编译的 KVM-VMI 2.11.93 旧版)不支持 USB 重定向功能,所以 libvirt 启动虚拟机时拒绝执行。
解决办法2:降级 libvirt 来兼容旧版 QEMU(不建议)
卸载前先备份虚拟机配置(关键!)
virsh dumpxml win7-i686 > ~/win7-backup.xml
卸载当前libvirt
sudo apt remove --purge libvirt-daemon-system libvirt-clients libvirt0 sudo apt autoremove
源码编译安装
下载 libvirt 5.6.0(和 KVM-VMI v7 分支最兼容的版本)
wget https://libvirt.org/sources/libvirt-5.6.0.tar.xz
tar -xf libvirt-5.6.0.tar.xz
cd libvirt-5.6.0
解决依赖问题
sudo apt update
安装 gnutls 开发包(包含 pkg-config 模块)+ 升级 gnutls
(1)
sudo apt install -y libgnutls28-dev libgnutls30 gnutls-bin
(2)
sudo apt install -y libnl-3-dev libnl-route-3-dev libnl-genl-3-dev
(3)
sudo apt install -y libxml2-dev libxml2
(4)
sudo apt install -y xsltproc libxslt1-dev
(5)
sudo apt install -y libdevmapper-dev
(6)
sudo apt install -y libpciaccess-dev配置编译(关闭不需要的功能,专注 KVM) ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-kvm --disable-xen --disable-lxc --disable-openvz
make -j$(nproc)
sudo make install
重启服务
sudo systemctl restart libvirtd
systemd 服务文件未被正确识别(但 libvirt 5.6.0 已安装成功)
验证版本
libvirtd --version
恢复虚拟机配置(无需重装系统,直接导入)
virsh define ~/win7-backup.xml
接下来会出现一系列的问题
编辑/启动虚拟机(和之前完全一样,数据不丢失)
现在探测机制宽松,不会触发 Permission denied
virsh edit win7-i686
virsh start win7-i686
最终解决办法(推荐这个):
1.查看usr/local/bin/qemu-system-x86_64的真实权限
ls -l /usr/local/bin/qemu-system-x86_64-rwxr-xr-x 1 root root 13918384 3月 22 11:34 /usr/local/bin/qemu-system-x86_64
判断所属用户、所属组均为root
2.永久允许libvirt使用 /usr/local/bin/qemu-system-x86_64 (直接编辑apparmor)
sudo nano /etc/apparmor.d/usr.sbin.libvirtd在文件中找到一段类似这样的内容
/usr/bin/* PUx,
将以下命令添加到附近
/usr/local/bin/* PUx,
保存退出重启
sudo systemctl reload apparmor sudo systemctl restart libvirtd3.编辑libvirt的qemu全局配置
sudo nano /etc/libvirt/qemu.conf添加:
user = "root"
group = "root"
qemu_binary = "/usr/local/bin/qemu-system-x86_64"
security_driver = "none" :关闭 libvirt 安全限制
dynamic_ownership = 0 :禁止自动改文件权限
4.重启libvirt生效
sudo systemctl stop libvirtd libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket sudo systemctl disable libvirtd.socket sudo systemctl enable libvirtd sudo systemctl start libvirtd之后关闭虚拟机,重启
安装virsh
1、
sudo apt install libvirt-clients
2、之后在执行sudo virsh list --all的时候遇到了以下问题

3、检查libvirtd服务未安装
sudo systemctl status libvirtd
4、安装
# 1. 先确保安装了完整的 libvirt 组件(如果没装的话)
sudo apt update
sudo apt install -y libvirt-daemon-system libvirt-clients qemu-kvm
# 2. 启动并设置开机自启
sudo systemctl start libvirtd
sudo systemctl enable libvirtd
# 3. 再次检查状态(应该显示 active (running))
sudo systemctl status libvirtd

问题
1、

这个分支在哪里切换?是在kvm目录下切换?还是在kvm-vmi目录下切换?
我在kvm目录下切换会出现编译打包错误的问题
因此,我实在kvm-vmi目录下切换的
2、我觉得我应该看着一部分





