|
libintrovirt v0.57.4
IntroVirt introspection library
|
This page describes the example programs included with IntroVirt. The main instructional example is vmcall_interface, which shows how to implement a custom hypercall interface between a Windows guest and an IntroVirt tool.
Example source files (marked with @example in code) are listed in the Examples menu in the navigation; each entry links to the full source. Use this page for walkthroughs, build, and usage; use the Examples list for the actual code.
Source (host tool): vmcall_interface.cc — listed in the Examples menu.
The vmcall_interface example demonstrates using the x86 vmcall instruction to communicate between a process running inside a Windows guest and an IntroVirt tool running on the host. The guest requests services (reverse a string, write-protect memory, protect the process) by executing vmcall with a service code; the hypervisor delivers the event to the IntroVirt tool, which performs the action and returns a status in RAX.
There are two components:
| Component | Location | Role |
|---|---|---|
| Host tool | examples/vmcall_interface (built with IntroVirt) | Attaches to the VM, handles hypercall and system-call events, implements the services. |
| Guest executable | examples/guest/vmcall_interface (build on Windows) | Runs inside the VM and issues vmcall to request each service. |
vmcall.Service codes used in this example:
| Code | Name | Description |
|---|---|---|
0xF000 | CSTRING_REVERSE | Reverse a C-string in place (pointer in RDX). |
0xF001 | WRITE_PROTECT | Make a memory region read-only (buffer in RDX, length in R8). |
0xF002 | PROTECT_PROCESS | Protect the calling process from termination, injection, and debugging. |
The host tool attaches to a domain, detects a Windows guest, enables system-call interception for NtTerminateProcess and NtOpenProcess (for cleanup and process protection), then polls for events. Hypercalls are handled in EventHandler::handle_hypercall(); system calls are used to clean up watchpoints on exit and to enforce process protection.
The callback receives EVENT_HYPERCALL, then reads the service code from RCX and dispatches:
The guest passes a pointer to a C-string in RDX. The tool maps it with map_guest_cstring, reverses it in place, and returns 0 on success:
The guest passes a buffer pointer in RDX and length in R8. The tool creates a watchpoint for writes to that region; on write it injects a fault. Watchpoints are stored per-PID and removed when the process exits (via NtTerminateProcess handling):
The tool adds the calling process’s PID to a protected set. In NtTerminateProcess it blocks termination of that PID (e.g. by setting the process handle to invalid); in NtOpenProcess it blocks opening the process with terminate/write/debug rights. Thus the process cannot be killed, injected into, or debugged by other guest processes.
On x64 Windows the first four integer/pointer arguments use RCX, RDX, R8, R9. The IntroVirt KVM patch treats a vmcall as an IntroVirt hypercall when RAX == 0xFACE. The guest assembler sets RAX, RCX (and RDX/ R8/ R9 as needed), then executes vmcall; the return status is in RAX.
Assemble with LLVM (e.g. llvm-ml -m64 -c vmcall.asm -o vmcall.obj).
The C side declares the assembler functions and uses them for each demo:
The vmcall_interface binary is built with IntroVirt. From the project root:
The executable is build/examples/vmcall_interface.
Build the guest code on a Windows VM with Clang/LLVM on the path (e.g. from LLVM releases).
examples/guest/vmcall_interface/build.ps1examples/guest/vmcall_interface/vmcall.asmexamples/guest/vmcall_interface/main.cvmcall_test.exe (or equivalent) available. Do not run it yet.Leave this running. You should see it attach and detect the Windows guest.
| Guest command | What it does |
|---|---|
vmcall_test.exe reverse-string | Reverses the string "Hello, IntroVirt!" in place via hypercall; prints original and reversed. |
vmcall_test.exe mem-protect | Asks the hypervisor to write-protect a buffer, then writes to it; the write triggers a fault and the program will crash (access violation) if protection is active. Use Ctrl+C to exit. |
vmcall_test.exe protect-process | Marks the process as protected. The hypervisor blocks termination and opening the process with dangerous rights; the process cannot be killed or debugged by other guest programs. Use Ctrl+C in the host vmcall_interface terminal to stop the tool and detach; then the guest process will exit. |
vmcall_interface is running so it can detach cleanly from the domain.vmcall; the host handles EVENT_HYPERCALL and returns status in RAX.For the full source, see examples/vmcall_interface.cc (host) and examples/guest/vmcall_interface/ (guest).