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 isr::cache::IsrCache;
5use vmi::{
6    VcpuId, VmiCore, VmiSession,
7    arch::amd64::Amd64,
8    driver::xen::VmiXenDriver,
9    os::{VmiOsProcess as _, windows::WindowsOs},
10};
11use xen::XenStore;
12
13fn main() -> Result<(), Box<dyn std::error::Error>> {
14    let domain_id = 'x: {
15        for name in &["win7", "win10", "win11", "ubuntu22"] {
16            if let Some(domain_id) = XenStore::new()?.domain_id_from_name(name)? {
17                break 'x domain_id;
18            }
19        }
20
21        panic!("Domain not found");
22    };
23
24    // Setup VMI.
25    let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
26    let core = VmiCore::new(driver)?;
27
28    // Try to find the kernel information.
29    // This is necessary in order to load the profile.
30    let kernel_info = {
31        // Pause the VM to get consistent state.
32        let _pause_guard = core.pause_guard()?;
33
34        // Get the register state for the first vCPU.
35        let registers = core.registers(VcpuId(0))?;
36
37        // On AMD64 architecture, the kernel is usually found using the
38        // `MSR_LSTAR` register, which contains the address of the system call
39        // handler. This register is set by the operating system during boot
40        // and is left unchanged (unless some rootkits are involved).
41        //
42        // Therefore, we can take an arbitrary registers at any point in time
43        // (as long as the OS has booted and the page tables are set up) and
44        // use them to find the kernel.
45        WindowsOs::find_kernel(&core, &registers)?.expect("kernel information")
46    };
47
48    // Load the profile.
49    // The profile contains offsets to kernel functions and data structures.
50    let isr = IsrCache::new("cache")?;
51    let entry = isr.entry_from_codeview(kernel_info.codeview)?;
52    let profile = entry.profile()?;
53
54    // Create the VMI session.
55    tracing::info!("Creating VMI session");
56    let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
57    let session = VmiSession::new(&core, &os);
58
59    // Pause the VM again to get consistent state.
60    let _pause_guard = session.pause_guard()?;
61
62    // Create a new `VmiState` with the current register.
63    let registers = session.registers(VcpuId(0))?;
64    let vmi = session.with_registers(&registers);
65
66    // Get the list of processes and print them.
67    for process in vmi.os().processes()? {
68        let process = process?;
69
70        println!(
71            "{} [{}] {} (root @ {})",
72            process.object()?,
73            process.id()?,
74            process.name()?,
75            process.translation_root()?
76        );
77    }
78
79    Ok(())
80}