KVM-based Virtual Machine Instrospection.
This project adds virtual machine introspection to the KVM hypervisor to monitor a running virtual machine without a guest agent.
This project is divided into 4 components:
kvm
: linux kernel with vmi patches for KVMqemu
: patched to allow introspectionnitro
: userland library which receives events, introspects the virtual machine state, and fills the semantic gaplibvmi
: virtual machine instrospection library with unified API acrossXen
andKVM
At the moment, 2 versions of VMI patches are available for QEMU/KVM
in this repository:
KVM-VMI
started as an improved fork of Nitro, a set of VMI patches
for QEMU/KVM
to intercept system calls and rebuild the execution context.
Nitro
is the name of the userland component that will receive and interpret the syscalls,
as well as the name of the set of patches for QEMU/KVM
.
Corresponding submodule branches:
kvm
:vmi
qemu
:vmi
nitro
:master
libvmi
:nitro
(Sorry for the confusing branches naming...)
Details:
Once the traps are set, the VM will be in a "paused" state and go back to the
hypervisor on every system call.
In details, the traps are working directly at the instruction level, on syscall
and sysret
, which means that you can also stop the VM when the system call
returns from the kernel.
When the VM is "paused", some introspection can be done by reading or writing
into the memory. Therefore it is possible to reconstruct VM state and understand
the system call context
(process name, system call name).
Furthermore, we are able to decode the system call
parameters and display what file is being created (in the case of NtCreateFile
,
for Windows
only).
A hooking API allows you to define callbacks
on top of the system calls you intercept:
def enter_NtCreateFile(syscall):
DesiredAccess = syscall.args[1]
object_attributes = syscall.args[2]
obj = ObjectAttributes(object_attributes, syscall.process)
buffer = obj.ObjectName.Buffer
access = FileAccessMask(DesiredAccess)
syscall.hook = {
'object_name': buffer,
'access': access.rights
}
Resulting in this output:
[
{
"event": {
"cr3": "0x76f9e000",
"vcpu": 0,
"rax": "0x52",
"direction": "enter",
"type": "syscall"
},
"name": "NtCreateFile",
"process": {
"pid": 2344,
"name": "powershell.exe"
},
"hook": {
"object_name": "\\??\\C:\\Program Files\\Windows Sidebar\\Gadgets\\PicturePuzzle.Gadget\\en-US\\gadget.xml",
"access": [
"SYNCHRONIZE",
"GENERIC_READ",
"FILE_READ_ATTRIBUTES"
]
}
},
]
A complete set of VMI APIs proposed by BitDefender
This is where the current effort is focused on.
Corresponding submodule branches:
kvm
:kvmi
qemu
:kvmi
nitro
:kvmi
libvmi
:kvmi
Go to the vagrant/
sub-directory to install a development environment for kvm-vmi
Unfortunately, it is not possible to compile the KVM modules as an out-of-tree
build. You will have to compile and install a new kernel along with the new modules.
This is only valid for the Nitro
set of patches:
- Start by compiling a new kernel in
kvm
- Reboot
- Make sure you loaded the modified kernel module (
make reload
) - Go to
nitro
to setup the userland component and intercept syscalls - Compile the modified version of
qemu
if you intend to analyze syscall events
Based on Jonas Pfoh
's work:
PRs accepted.
Small note: If editing the Readme, please conform to the standard-readme specification.