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