Skip to main content

basic_process_list/
basic-process-list.rs

1//! This example demonstrates how to enumerate the running processes of a
2//! Windows guest running inside a Xen domain.
3
4use anyhow::{Context as _, Error};
5use isr::cache::IsrCache;
6use vmi::{
7    VcpuId, VmiCore, VmiSession,
8    arch::amd64::Amd64,
9    driver::xen::VmiXenDriver,
10    os::{VmiOsProcess as _, windows::WindowsOs},
11};
12
13fn main() -> Result<(), Error> {
14    // Setup VMI.
15    let driver = VmiXenDriver::<Amd64>::try_from_env()?
16        .context("invalid VMI_XEN_DOMAIN environment variable")?;
17    let core = VmiCore::new(driver)?;
18
19    // Try to find the kernel information.
20    // This is necessary in order to load the profile.
21    let kernel_info = {
22        // Pause the VM to get consistent state.
23        let _pause_guard = core.pause_guard()?;
24
25        // Get the register state for the first vCPU.
26        let registers = core.registers(VcpuId(0))?;
27
28        // On AMD64 architecture, the kernel is usually found using the
29        // `MSR_LSTAR` register, which contains the address of the system call
30        // handler. This register is set by the operating system during boot
31        // and is left unchanged (unless some rootkits are involved).
32        //
33        // Therefore, we can take an arbitrary registers at any point in time
34        // (as long as the OS has booted and the page tables are set up) and
35        // use them to find the kernel.
36        WindowsOs::find_kernel(&core, &registers)?.expect("kernel information")
37    };
38
39    // Load the profile.
40    // The profile contains offsets to kernel functions and data structures.
41    let isr = IsrCache::new("cache")?;
42    let entry = isr.entry_from_codeview(kernel_info.codeview)?;
43    let profile = entry.profile()?;
44
45    // Create the VMI session.
46    tracing::info!("Creating VMI session");
47    let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
48    let session = VmiSession::new(&core, &os);
49
50    // Pause the VM again to get consistent state.
51    let paused = session.pause_guard()?;
52
53    // Create a new `VmiState` with the boot CPU registers.
54    let vmi = paused.state();
55
56    // Get the list of processes and print them.
57    for process in vmi.os().processes()? {
58        let process = process?;
59
60        println!(
61            "{} [{}] {} (root @ {})",
62            process.object()?,
63            process.id()?,
64            process.name()?,
65            process.translation_root()?
66        );
67    }
68
69    Ok(())
70}