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, ®isters)?.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 paused = session.pause_guard()?;
61
62 // Create a new `VmiState` with the boot CPU registers.
63 let vmi = paused.state();
64
65 // Get the list of processes and print them.
66 for process in vmi.os().processes()? {
67 let process = process?;
68
69 println!(
70 "{} [{}] {} (root @ {})",
71 process.object()?,
72 process.id()?,
73 process.name()?,
74 process.translation_root()?
75 );
76 }
77
78 Ok(())
79}