Introduction
libintrovirt is the core userland library of IntroVirt. It gives you programmatic access to a running virtual machine from the host: read and write guest memory, intercept system calls and hypercalls, set breakpoints and watchpoints, and inject code or system calls into the guest. IntroVirt works with a patched KVM hypervisor (see kvm-introvirt) and supports Windows guests with full NT system call and API coverage.
Typical use cases include monitoring or blocking guest behavior, building security and forensics tools, debugging, and implementing custom hypercall interfaces between guest and host.
Prerequisites
- A VM running on a host with the IntroVirt KVM patch (kvm-introvirt) loaded
- libintrovirt and its dependencies built and installed (see the project README)
- For Windows guests: libmspdb for kernel structure support
Quick start: system call monitor
The following minimal example attaches to a domain (VM), detects a Windows guest, enables system call interception, and prints each syscall as it returns. It shows the core flow: attach → detect guest → configure filter → poll with an EventCallback.
#include <csignal>
#include <iostream>
static std::unique_ptr<Domain>
domain;
public:
void process_event(
Event& event)
override {
if (event.
type() == EventType::EVENT_FAST_SYSCALL) {
event.syscall().hook_return(true);
return;
}
if (event.
type() == EventType::EVENT_FAST_SYSCALL_RET) {
auto& task = event.task();
std::cout << "[" << task.pid() << ":" << task.tid() << "] "
<< task.process_name() << " " << event.syscall().name() << "\n";
}
}
};
int main(
int argc,
char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <domain>\n";
return 1;
}
auto hypervisor = Hypervisor::instance();
domain = hypervisor->attach_domain(argv[1]);
if (!
domain->detect_guest()) {
std::cerr << "Failed to detect guest\n";
return 1;
}
if (
domain->guest()->os() != OS::Windows) {
std::cerr << "This example requires a Windows guest\n";
return 1;
}
domain->system_call_filter().enabled(
true);
domain->intercept_system_calls(
true);
MinimalSyscallMonitor mon;
return 0;
}
Interface for an event poller callback.
Definition EventCallback.hh:29
Interface class for hypervisor events.
Definition Event.hh:43
virtual EventType type() const =0
Get the type of event.
A representation of a Windows Guest OS.
Definition WindowsGuest.hh:33
virtual void default_syscall_filter(SystemCallFilter &filter) const =0
Configure a system call filter for all supported calls.
int main(int argc, char **argv)
Definition main.c:35
Classes related to Microsoft Windows guests.
Definition LanguageId.hh:21
Core IntroVirt classes.
Definition Cr0.hh:20
void sig_handler(int signum)
Definition vmcall_interface.cc:571
unique_ptr< Domain > domain
Definition vmcall_interface.cc:48
Build and run (replace win10 with your domain name or ID):
g++ main.cc -o basic_syscallmon -lintrovirt
sudo ./basic_syscallmon win10
Use Ctrl+C to detach cleanly. For a full-featured syscall monitor with filtering and JSON output, see the ivsyscallmon tool.
Main concepts
- Hypervisor – Get a hypervisor instance and attach to domains (VMs) by name or PID.
- Domain – Represents one VM: create breakpoints and watchpoints, single-step, inject calls, and poll for events.
- Vcpu – A virtual CPU: read or modify registers and control execution (e.g. inject exceptions).
- Guest – The OS running in the domain (e.g. Windows): guest detection, memory allocation, and OS-specific helpers.
- Event – Delivered to your EventCallback: system calls, hypercalls, breakpoints, watchpoints, and more.
Events are handled in a single callback; you switch on event.type() and cast to WindowsEvent when you need Windows-specific data (e.g. syscall handler, task info).
Example programs and tools
- Example documentation (Example documentation) – Walkthroughs and detailed docs (e.g. vmcall_interface: hypercalls, guest/host setup, build, usage).
- Examples menu – List of example source files (vmcall_interface, tools) with vmcall_interface.cc and others.
- IntroVirt tools – Ready-made utilities (ivsyscallmon, ivprocinfo, ivmemwatch, ivreadfile, etc.) in the Examples list; use them as reference or as-is.
Building the documentation
From the project root:
mkdir -p build && cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDOXYGEN=ON ..
ninja doc
Output is in build/html/. The API docs are also published to GitHub Pages on push to main.