basic_process_list/
basic-process-list.rs

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