pub struct WindowsOs<Driver>where
Driver: VmiDriver,{ /* private fields */ }os-windows only.Expand description
VMI operations for the Windows operating system.
WindowsOs provides methods and utilities for introspecting a Windows-based
virtual machine. It encapsulates Windows-specific knowledge and operations,
allowing for high-level interactions with the guest OS structures and processes.
§Usage
Create an instance of WindowsOs using a Profile that contains information
about the specific Windows version being introspected:
use isr::cache::IsrCache;
use vmi::{
VcpuId, VmiCore,
arch::amd64::Amd64,
driver::{VmiQueryRegisters, VmiRead, VmiVmControl},
os::windows::WindowsOs,
};
// Setup VMI.
let core = VmiCore::new(driver)?;
// Try to find the kernel information.
// This is necessary in order to load the profile.
let kernel_info = {
let _guard = core.pause_guard()?;
let registers = core.registers(VcpuId(0))?;
WindowsOs::find_kernel(&core, ®isters)?.expect("kernel information")
};
// Load the profile using the ISR library.
let isr = IsrCache::new("cache")?;
let entry = isr.entry_from_codeview(kernel_info.codeview)?;
let profile = entry.profile()?;
// Create a new `WindowsOs` instance.
let os = WindowsOs::<Driver>::new(&profile)?;§Important Notes
-
Many methods of this struct require pausing the VM to ensure consistency. Use
pause_guardwhen performing operations that might be affected by concurrent changes in the guest OS. -
The behavior and accuracy of some methods may vary depending on the Windows version being introspected. Always ensure your
Profilematches the guest OS version.
§Examples
Retrieving information about the current process:
let process = vmi.os().current_process()?;
let process_id = process.id()?;
let process_name = process.name()?;
println!("Current process: {} (PID: {})", process_name, process_id);Enumerating all processes:
for process in vmi.os().processes()? {
let process = process?;
println!("Process: {} (PID: {})", process.name()?, process.id()?);
}§Safety
While this struct doesn’t use unsafe code directly, many of its methods interact with raw memory of the guest OS. Incorrect usage can lead to invalid memory access or misinterpretation of data. Always ensure you’re working with the correct memory regions and OS structures.
Implementations§
Source§impl<Driver> WindowsOs<Driver>
impl<Driver> WindowsOs<Driver>
Sourcepub const NtCurrentProcess32: u64 = 0xffff_ffff
pub const NtCurrentProcess32: u64 = 0xffff_ffff
32-bit current process pseudo-handle (-1).
Sourcepub const NtCurrentProcess64: u64 = 0xffff_ffff_ffff_ffff
pub const NtCurrentProcess64: u64 = 0xffff_ffff_ffff_ffff
64-bit current process pseudo-handle (-1).
Sourcepub const NtCurrentThread32: u64 = 0xffff_fffe
pub const NtCurrentThread32: u64 = 0xffff_fffe
32-bit current thread pseudo-handle (-2).
Sourcepub const NtCurrentThread64: u64 = 0xffff_ffff_ffff_fffe
pub const NtCurrentThread64: u64 = 0xffff_ffff_ffff_fffe
64-bit current thread pseudo-handle (-2).
Sourcepub fn new(profile: &Profile<'_>) -> Result<WindowsOs<Driver>, VmiError>
pub fn new(profile: &Profile<'_>) -> Result<WindowsOs<Driver>, VmiError>
Creates a new WindowsOs instance.
Examples found in repository?
525fn main() -> Result<(), Box<dyn std::error::Error>> {
526 tracing_subscriber::fmt()
527 .with_max_level(tracing::Level::DEBUG)
528 .init();
529
530 let domain_id = 'x: {
531 for name in &["win7", "win10", "win11", "ubuntu22"] {
532 if let Some(domain_id) = XenStore::new()?.domain_id_from_name(name)? {
533 break 'x domain_id;
534 }
535 }
536
537 panic!("Domain not found");
538 };
539
540 tracing::debug!(?domain_id);
541
542 // Setup VMI.
543 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
544 let core = VmiCore::new(driver)?;
545
546 // Try to find the kernel information.
547 // This is necessary in order to load the profile.
548 let kernel_info = {
549 let _pause_guard = core.pause_guard()?;
550 let regs = core.registers(0.into())?;
551
552 WindowsOs::find_kernel(&core, ®s)?.expect("kernel information")
553 };
554
555 // Load the profile.
556 // The profile contains offsets to kernel functions and data structures.
557 let isr = IsrCache::new("cache")?;
558 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
559 let profile = entry.profile()?;
560
561 // Create the VMI session.
562 tracing::info!("Creating VMI session");
563 let terminate_flag = Arc::new(AtomicBool::new(false));
564 signal_hook::flag::register(signal_hook::consts::SIGHUP, terminate_flag.clone())?;
565 signal_hook::flag::register(signal_hook::consts::SIGINT, terminate_flag.clone())?;
566 signal_hook::flag::register(signal_hook::consts::SIGALRM, terminate_flag.clone())?;
567 signal_hook::flag::register(signal_hook::consts::SIGTERM, terminate_flag.clone())?;
568
569 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
570 let session = VmiSession::new(&core, &os);
571
572 session.handle(|session| Monitor::new(session, &profile, terminate_flag))?;
573
574 Ok(())
575}More examples
15pub fn create_vmi_session() -> Result<Session, Box<dyn std::error::Error>> {
16 tracing_subscriber::fmt()
17 .with_max_level(tracing::Level::DEBUG)
18 .with_target(false)
19 .init();
20
21 let domain_id = 'x: {
22 for name in &["win7", "win10", "win11", "ubuntu22"] {
23 if let Some(domain_id) = XenStore::new()?.domain_id_from_name(name)? {
24 break 'x domain_id;
25 }
26 }
27
28 panic!("Domain not found");
29 };
30
31 tracing::debug!(?domain_id);
32
33 // Setup VMI.
34 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
35 let core = VmiCore::new(driver)?;
36
37 // Try to find the kernel information.
38 // This is necessary in order to load the profile.
39 let kernel_info = {
40 // Pause the vCPU to get consistent state.
41 let _pause_guard = core.pause_guard()?;
42
43 // Get the register state for the first vCPU.
44 let registers = core.registers(VcpuId(0))?;
45
46 // On AMD64 architecture, the kernel is usually found using the
47 // `MSR_LSTAR` register, which contains the address of the system call
48 // handler. This register is set by the operating system during boot
49 // and is left unchanged (unless some rootkits are involved).
50 //
51 // Therefore, we can take an arbitrary registers at any point in time
52 // (as long as the OS has booted and the page tables are set up) and
53 // use them to find the kernel.
54 WindowsOs::find_kernel(&core, ®isters)?.expect("kernel information")
55 };
56
57 // Load the profile.
58 // The profile contains offsets to kernel functions and data structures.
59 let isr = IsrCache::new("cache")?;
60 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
61 let entry = Box::leak(Box::new(entry));
62 let profile = entry.profile()?;
63
64 // Create the VMI session.
65 tracing::info!("Creating VMI session");
66 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
67
68 // Please don't do this in production code.
69 // This is only done for the sake of the example.
70 let core = Box::leak(Box::new(core));
71 let os = Box::leak(Box::new(os));
72
73 Ok((VmiSession::new(core, os), profile))
74}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}245fn main() -> Result<(), Error> {
246 let filter = EnvFilter::default()
247 .add_directive(tracing::Level::DEBUG.into())
248 .add_directive("reqwest=warn".parse()?)
249 .add_directive("rustls=warn".parse()?);
250
251 tracing_subscriber::fmt()
252 .with_env_filter(filter)
253 .with_target(false)
254 .init();
255
256 let domain_id = match std::env::var("VMI_XEN_DOMAIN_ID") {
257 Ok(domain_id) => XenDomainId(
258 domain_id
259 .parse()
260 .context("invalid VMI_XEN_DOMAIN_ID environment variable")?,
261 ),
262 Err(_) => {
263 let domain_name = std::env::var("VMI_XEN_DOMAIN_NAME")
264 .context("invalid VMI_XEN_DOMAIN_NAME environment variable")?;
265
266 tracing::info!(%domain_name, "resolving domain ID");
267
268 match XenStore::new()?.domain_id_from_name(&domain_name)? {
269 Some(domain_id) => domain_id,
270 None => return Err(anyhow::anyhow!("domain not found: {domain_name}")),
271 }
272 }
273 };
274
275 // Setup VMI.
276 tracing::info!(%domain_id, "setting up VMI");
277 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
278 let core = VmiCore::new(driver)?;
279
280 // Try to find the kernel information.
281 // This is necessary in order to load the profile.
282 let kernel_info = {
283 let _pause_guard = core.pause_guard()?;
284 let registers = core.registers(VcpuId(0))?;
285
286 WindowsOs::find_kernel(&core, ®isters)?.context("cannot find kernel information")?
287 };
288
289 // Load the kernel profile.
290 // The profile contains offsets to kernel functions and data structures.
291 tracing::info!(codeview = ?kernel_info.codeview, "loading kernel profile");
292 let isr = IsrCache::new("cache")?;
293 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
294 let profile = entry.profile()?;
295
296 // Create the VMI session.
297 tracing::info!("creating VMI session");
298 let terminate_flag = Arc::new(AtomicBool::new(false));
299 signal_hook::flag::register(signal_hook::consts::SIGHUP, terminate_flag.clone())?;
300 signal_hook::flag::register(signal_hook::consts::SIGINT, terminate_flag.clone())?;
301 signal_hook::flag::register(signal_hook::consts::SIGALRM, terminate_flag.clone())?;
302 signal_hook::flag::register(signal_hook::consts::SIGTERM, terminate_flag.clone())?;
303
304 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
305 let session = VmiSession::new(&core, &os);
306
307 let handler = NetIo::default();
308
309 //
310 // The following `let ncrypt_* = ...` lines demonstrate how to manually
311 // resolve a module, load its profile (symbols) and add it to the resolver
312 // via `with_module(_in_process)`.
313 //
314 // Note that this is not strictly necessary, as `ModuleResolver::resolve()`
315 // will automatically resolve modules if they are not explicitly added.
316 //
317 // Manually resolving modules can be useful in cases where you want to deal
318 // with the resolved information (base address, profile) in other places.
319 //
320
321 let ncrypt_resolved = {
322 let paused = session.pause_guard()?;
323 let vmi = paused.state();
324
325 // Calling `resolve_user_module(&vmi, &isr, "ncrypt.dll", "lsass.exe")`
326 // would also work, but this demonstrates how to use a custom predicate.
327 //
328 // Also, `match_lsass` is more strict, because it specifically looks
329 // for "lsass.exe" in SessionId 0 (therefore, avoiding potential false
330 // positives or potential malicious processes).
331 vmi::utils::resolver::resolve_user_module(&vmi, &isr, "ncrypt.dll", match_lsass)?
332 .context("ncrypt.dll not found in lsass.exe")?
333 };
334
335 let ncrypt_process = ncrypt_resolved
336 .process
337 .context("resolved ncrypt.dll is not associated with a process")?;
338
339 let ncrypt_entry = isr
340 .entry_from_codeview(ncrypt_resolved.debug_signature)
341 .context("cannot find symbols for ncrypt.dll")?;
342
343 let ncrypt_profile = ncrypt_entry
344 .profile()
345 .context("cannot load profile for ncrypt.dll")?;
346
347 // The `SymbolCache` holds the resolved `isr::Entry` items.
348 let mut cache = SymbolCache::default();
349 let modules = ModuleResolver::default()
350 // `with_kernel` MUST be called if `Event` variants reference kernel
351 // symbols - like `NtWriteFile` in this example.
352 //
353 // This is because the "kernel" module is always optional.
354 .with_kernel(kernel_info.base_address, profile)
355 .with_module_in_process(
356 Module::NcryptDll,
357 ncrypt_process,
358 ncrypt_resolved.image_base,
359 ncrypt_profile,
360 )
361 // This will automatically resolve the `netio.sys` module and load
362 // its profile.
363 //
364 // Note that if we hadn't called `with_module_in_process` for
365 // `ncrypt.dll`, it would also be automatically resolved here.
366 .resolve(&session, &isr, &mut cache)?;
367
368 // Finally, we collect the events according to the resolved information
369 // and the metadata.
370 //
371 // For example, if some module/event is marked as `optional` and the
372 // resolver fails to resolve it, then it will simply not be included
373 // in the `events`.
374 let events = modules.into_events()?;
375
376 // And we're ready to create the reactor!
377 session.handle(|session| {
378 Ok(Reactor::new(session, handler, events)?.with_termination_flag(terminate_flag))
379 })?;
380
381 Ok(())
382}Sourcepub fn with_kernel_base(
profile: &Profile<'_>,
kernel_base: Va,
) -> Result<WindowsOs<Driver>, VmiError>
pub fn with_kernel_base( profile: &Profile<'_>, kernel_base: Va, ) -> Result<WindowsOs<Driver>, VmiError>
Creates a new WindowsOs instance with a known kernel base address.
Examples found in repository?
393fn main() -> Result<(), Box<dyn std::error::Error>> {
394 tracing_subscriber::fmt()
395 .with_max_level(tracing::Level::DEBUG)
396 .with_ansi(false)
397 .init();
398
399 // First argument is the path to the dump file.
400 let args = std::env::args().collect::<Vec<_>>();
401 if args.len() != 2 {
402 eprintln!("Usage: {} <dump-file>", args[0]);
403 std::process::exit(1);
404 }
405
406 let dump_file = &args[1];
407
408 // Setup VMI.
409 let driver = Driver::new(dump_file)?;
410 let core = VmiCore::new(driver)?;
411
412 let registers = core.registers(VcpuId(0))?;
413
414 // Try to find the kernel information.
415 // This is necessary in order to load the profile.
416 let kernel_info = WindowsOs::find_kernel(&core, ®isters)?.expect("kernel information");
417 tracing::info!(?kernel_info, "Kernel information");
418
419 // Load the profile.
420 // The profile contains offsets to kernel functions and data structures.
421 let isr = IsrCache::new("cache")?;
422 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
423 let profile = entry.profile()?;
424
425 // Create the VMI session.
426 tracing::info!("Creating VMI session");
427 let os = WindowsOs::<Driver>::with_kernel_base(&profile, kernel_info.base_address)?;
428 let session = VmiSession::new(&core, &os);
429
430 let vmi = session.with_registers(®isters);
431 let root_directory = vmi.os().object_root_directory()?;
432
433 println!("Kernel Modules:");
434 println!("=================================================");
435 enumerate_kernel_modules(&vmi)?;
436
437 println!("Object Tree (root directory: {}):", root_directory.va());
438 println!("=================================================");
439 enumerate_directory_object(&root_directory, 0)?;
440
441 println!("Processes:");
442 println!("=================================================");
443 enumerate_processes(&vmi)?;
444
445 Ok(())
446}Sourcepub fn offsets(vmi: VmiState<'_, WindowsOs<Driver>>) -> &Offsets
pub fn offsets(vmi: VmiState<'_, WindowsOs<Driver>>) -> &Offsets
Returns a reference to the Windows-specific memory offsets.
Sourcepub fn symbols(vmi: VmiState<'_, WindowsOs<Driver>>) -> &Symbols
pub fn symbols(vmi: VmiState<'_, WindowsOs<Driver>>) -> &Symbols
Returns a reference to the Windows-specific symbols.
Sourcepub fn find_kernel(
vmi: &VmiCore<Driver>,
registers: &<<Driver as VmiDriver>::Architecture as Architecture>::Registers,
) -> Result<Option<WindowsKernelInformation>, VmiError>
pub fn find_kernel( vmi: &VmiCore<Driver>, registers: &<<Driver as VmiDriver>::Architecture as Architecture>::Registers, ) -> Result<Option<WindowsKernelInformation>, VmiError>
Locates the Windows kernel in memory based on the CPU registers. This function is architecture-specific.
On AMD64, the kernel is located by taking the MSR_LSTAR value and
reading the virtual memory page by page backwards until the MZ header
is found.
Examples found in repository?
525fn main() -> Result<(), Box<dyn std::error::Error>> {
526 tracing_subscriber::fmt()
527 .with_max_level(tracing::Level::DEBUG)
528 .init();
529
530 let domain_id = 'x: {
531 for name in &["win7", "win10", "win11", "ubuntu22"] {
532 if let Some(domain_id) = XenStore::new()?.domain_id_from_name(name)? {
533 break 'x domain_id;
534 }
535 }
536
537 panic!("Domain not found");
538 };
539
540 tracing::debug!(?domain_id);
541
542 // Setup VMI.
543 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
544 let core = VmiCore::new(driver)?;
545
546 // Try to find the kernel information.
547 // This is necessary in order to load the profile.
548 let kernel_info = {
549 let _pause_guard = core.pause_guard()?;
550 let regs = core.registers(0.into())?;
551
552 WindowsOs::find_kernel(&core, ®s)?.expect("kernel information")
553 };
554
555 // Load the profile.
556 // The profile contains offsets to kernel functions and data structures.
557 let isr = IsrCache::new("cache")?;
558 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
559 let profile = entry.profile()?;
560
561 // Create the VMI session.
562 tracing::info!("Creating VMI session");
563 let terminate_flag = Arc::new(AtomicBool::new(false));
564 signal_hook::flag::register(signal_hook::consts::SIGHUP, terminate_flag.clone())?;
565 signal_hook::flag::register(signal_hook::consts::SIGINT, terminate_flag.clone())?;
566 signal_hook::flag::register(signal_hook::consts::SIGALRM, terminate_flag.clone())?;
567 signal_hook::flag::register(signal_hook::consts::SIGTERM, terminate_flag.clone())?;
568
569 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
570 let session = VmiSession::new(&core, &os);
571
572 session.handle(|session| Monitor::new(session, &profile, terminate_flag))?;
573
574 Ok(())
575}More examples
393fn main() -> Result<(), Box<dyn std::error::Error>> {
394 tracing_subscriber::fmt()
395 .with_max_level(tracing::Level::DEBUG)
396 .with_ansi(false)
397 .init();
398
399 // First argument is the path to the dump file.
400 let args = std::env::args().collect::<Vec<_>>();
401 if args.len() != 2 {
402 eprintln!("Usage: {} <dump-file>", args[0]);
403 std::process::exit(1);
404 }
405
406 let dump_file = &args[1];
407
408 // Setup VMI.
409 let driver = Driver::new(dump_file)?;
410 let core = VmiCore::new(driver)?;
411
412 let registers = core.registers(VcpuId(0))?;
413
414 // Try to find the kernel information.
415 // This is necessary in order to load the profile.
416 let kernel_info = WindowsOs::find_kernel(&core, ®isters)?.expect("kernel information");
417 tracing::info!(?kernel_info, "Kernel information");
418
419 // Load the profile.
420 // The profile contains offsets to kernel functions and data structures.
421 let isr = IsrCache::new("cache")?;
422 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
423 let profile = entry.profile()?;
424
425 // Create the VMI session.
426 tracing::info!("Creating VMI session");
427 let os = WindowsOs::<Driver>::with_kernel_base(&profile, kernel_info.base_address)?;
428 let session = VmiSession::new(&core, &os);
429
430 let vmi = session.with_registers(®isters);
431 let root_directory = vmi.os().object_root_directory()?;
432
433 println!("Kernel Modules:");
434 println!("=================================================");
435 enumerate_kernel_modules(&vmi)?;
436
437 println!("Object Tree (root directory: {}):", root_directory.va());
438 println!("=================================================");
439 enumerate_directory_object(&root_directory, 0)?;
440
441 println!("Processes:");
442 println!("=================================================");
443 enumerate_processes(&vmi)?;
444
445 Ok(())
446}15pub fn create_vmi_session() -> Result<Session, Box<dyn std::error::Error>> {
16 tracing_subscriber::fmt()
17 .with_max_level(tracing::Level::DEBUG)
18 .with_target(false)
19 .init();
20
21 let domain_id = 'x: {
22 for name in &["win7", "win10", "win11", "ubuntu22"] {
23 if let Some(domain_id) = XenStore::new()?.domain_id_from_name(name)? {
24 break 'x domain_id;
25 }
26 }
27
28 panic!("Domain not found");
29 };
30
31 tracing::debug!(?domain_id);
32
33 // Setup VMI.
34 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
35 let core = VmiCore::new(driver)?;
36
37 // Try to find the kernel information.
38 // This is necessary in order to load the profile.
39 let kernel_info = {
40 // Pause the vCPU to get consistent state.
41 let _pause_guard = core.pause_guard()?;
42
43 // Get the register state for the first vCPU.
44 let registers = core.registers(VcpuId(0))?;
45
46 // On AMD64 architecture, the kernel is usually found using the
47 // `MSR_LSTAR` register, which contains the address of the system call
48 // handler. This register is set by the operating system during boot
49 // and is left unchanged (unless some rootkits are involved).
50 //
51 // Therefore, we can take an arbitrary registers at any point in time
52 // (as long as the OS has booted and the page tables are set up) and
53 // use them to find the kernel.
54 WindowsOs::find_kernel(&core, ®isters)?.expect("kernel information")
55 };
56
57 // Load the profile.
58 // The profile contains offsets to kernel functions and data structures.
59 let isr = IsrCache::new("cache")?;
60 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
61 let entry = Box::leak(Box::new(entry));
62 let profile = entry.profile()?;
63
64 // Create the VMI session.
65 tracing::info!("Creating VMI session");
66 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
67
68 // Please don't do this in production code.
69 // This is only done for the sake of the example.
70 let core = Box::leak(Box::new(core));
71 let os = Box::leak(Box::new(os));
72
73 Ok((VmiSession::new(core, os), profile))
74}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}245fn main() -> Result<(), Error> {
246 let filter = EnvFilter::default()
247 .add_directive(tracing::Level::DEBUG.into())
248 .add_directive("reqwest=warn".parse()?)
249 .add_directive("rustls=warn".parse()?);
250
251 tracing_subscriber::fmt()
252 .with_env_filter(filter)
253 .with_target(false)
254 .init();
255
256 let domain_id = match std::env::var("VMI_XEN_DOMAIN_ID") {
257 Ok(domain_id) => XenDomainId(
258 domain_id
259 .parse()
260 .context("invalid VMI_XEN_DOMAIN_ID environment variable")?,
261 ),
262 Err(_) => {
263 let domain_name = std::env::var("VMI_XEN_DOMAIN_NAME")
264 .context("invalid VMI_XEN_DOMAIN_NAME environment variable")?;
265
266 tracing::info!(%domain_name, "resolving domain ID");
267
268 match XenStore::new()?.domain_id_from_name(&domain_name)? {
269 Some(domain_id) => domain_id,
270 None => return Err(anyhow::anyhow!("domain not found: {domain_name}")),
271 }
272 }
273 };
274
275 // Setup VMI.
276 tracing::info!(%domain_id, "setting up VMI");
277 let driver = VmiXenDriver::<Amd64>::new(domain_id)?;
278 let core = VmiCore::new(driver)?;
279
280 // Try to find the kernel information.
281 // This is necessary in order to load the profile.
282 let kernel_info = {
283 let _pause_guard = core.pause_guard()?;
284 let registers = core.registers(VcpuId(0))?;
285
286 WindowsOs::find_kernel(&core, ®isters)?.context("cannot find kernel information")?
287 };
288
289 // Load the kernel profile.
290 // The profile contains offsets to kernel functions and data structures.
291 tracing::info!(codeview = ?kernel_info.codeview, "loading kernel profile");
292 let isr = IsrCache::new("cache")?;
293 let entry = isr.entry_from_codeview(kernel_info.codeview)?;
294 let profile = entry.profile()?;
295
296 // Create the VMI session.
297 tracing::info!("creating VMI session");
298 let terminate_flag = Arc::new(AtomicBool::new(false));
299 signal_hook::flag::register(signal_hook::consts::SIGHUP, terminate_flag.clone())?;
300 signal_hook::flag::register(signal_hook::consts::SIGINT, terminate_flag.clone())?;
301 signal_hook::flag::register(signal_hook::consts::SIGALRM, terminate_flag.clone())?;
302 signal_hook::flag::register(signal_hook::consts::SIGTERM, terminate_flag.clone())?;
303
304 let os = WindowsOs::<VmiXenDriver<Amd64>>::new(&profile)?;
305 let session = VmiSession::new(&core, &os);
306
307 let handler = NetIo::default();
308
309 //
310 // The following `let ncrypt_* = ...` lines demonstrate how to manually
311 // resolve a module, load its profile (symbols) and add it to the resolver
312 // via `with_module(_in_process)`.
313 //
314 // Note that this is not strictly necessary, as `ModuleResolver::resolve()`
315 // will automatically resolve modules if they are not explicitly added.
316 //
317 // Manually resolving modules can be useful in cases where you want to deal
318 // with the resolved information (base address, profile) in other places.
319 //
320
321 let ncrypt_resolved = {
322 let paused = session.pause_guard()?;
323 let vmi = paused.state();
324
325 // Calling `resolve_user_module(&vmi, &isr, "ncrypt.dll", "lsass.exe")`
326 // would also work, but this demonstrates how to use a custom predicate.
327 //
328 // Also, `match_lsass` is more strict, because it specifically looks
329 // for "lsass.exe" in SessionId 0 (therefore, avoiding potential false
330 // positives or potential malicious processes).
331 vmi::utils::resolver::resolve_user_module(&vmi, &isr, "ncrypt.dll", match_lsass)?
332 .context("ncrypt.dll not found in lsass.exe")?
333 };
334
335 let ncrypt_process = ncrypt_resolved
336 .process
337 .context("resolved ncrypt.dll is not associated with a process")?;
338
339 let ncrypt_entry = isr
340 .entry_from_codeview(ncrypt_resolved.debug_signature)
341 .context("cannot find symbols for ncrypt.dll")?;
342
343 let ncrypt_profile = ncrypt_entry
344 .profile()
345 .context("cannot load profile for ncrypt.dll")?;
346
347 // The `SymbolCache` holds the resolved `isr::Entry` items.
348 let mut cache = SymbolCache::default();
349 let modules = ModuleResolver::default()
350 // `with_kernel` MUST be called if `Event` variants reference kernel
351 // symbols - like `NtWriteFile` in this example.
352 //
353 // This is because the "kernel" module is always optional.
354 .with_kernel(kernel_info.base_address, profile)
355 .with_module_in_process(
356 Module::NcryptDll,
357 ncrypt_process,
358 ncrypt_resolved.image_base,
359 ncrypt_profile,
360 )
361 // This will automatically resolve the `netio.sys` module and load
362 // its profile.
363 //
364 // Note that if we hadn't called `with_module_in_process` for
365 // `ncrypt.dll`, it would also be automatically resolved here.
366 .resolve(&session, &isr, &mut cache)?;
367
368 // Finally, we collect the events according to the resolved information
369 // and the metadata.
370 //
371 // For example, if some module/event is marked as `optional` and the
372 // resolver fails to resolve it, then it will simply not be included
373 // in the `events`.
374 let events = modules.into_events()?;
375
376 // And we're ready to create the reactor!
377 session.handle(|session| {
378 Ok(Reactor::new(session, handler, events)?.with_termination_flag(terminate_flag))
379 })?;
380
381 Ok(())
382}Sourcepub fn kernel_information_string_ex(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<Option<String>, VmiError>
pub fn kernel_information_string_ex( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<Option<String>, VmiError>
Sourcepub fn is_kernel_handle(
vmi: VmiState<'_, WindowsOs<Driver>>,
handle: u64,
) -> Result<bool, VmiError>
pub fn is_kernel_handle( vmi: VmiState<'_, WindowsOs<Driver>>, handle: u64, ) -> Result<bool, VmiError>
Checks if the given handle is a kernel handle.
A kernel handle is a handle with the highest bit set.
Sourcepub fn lowest_user_address(
_vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<Va, VmiError>
pub fn lowest_user_address( _vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<Va, VmiError>
Returns the lowest user-mode address.
This method returns a constant value (0x10000) representing the lowest address that can be used by user-mode applications in Windows.
§Notes
-
Windows creates a
NO_ACCESSVAD (Virtual Address Descriptor) for the first 64KB of virtual memory. This means the VA range 0-0x10000 is off-limits for usage. -
This behavior is consistent across all Windows versions from XP through recent Windows 11, and applies to x86, x64, and ARM64 architectures.
-
Many Windows APIs leverage this fact to determine whether an input argument is a pointer or not. Here are two notable examples:
-
The
FindResource()function accepts anlpNameparameter of typeLPCTSTR, which can be either:-
A pointer to a valid string
-
A value created by
MAKEINTRESOURCE(ID)This allows
FindResource()to acceptWORDvalues (unsigned shorts) with a maximum value of 0xFFFF, distinguishing them from valid memory addresses.
-
-
The
AddAtom()function similarly accepts anlpStringparameter of typeLPCTSTR. This parameter can be:- A pointer to a null-terminated string (max 255 bytes)
- An integer atom converted using the
MAKEINTATOM(ID)macro
In both cases, the API can distinguish between valid pointers (which will be above 0x10000) and integer values (which will be below 0x10000), allowing for flexible parameter usage without ambiguity.
-
Sourcepub fn is_valid_user_address(
vmi: VmiState<'_, WindowsOs<Driver>>,
address: Va,
) -> Result<bool, VmiError>
pub fn is_valid_user_address( vmi: VmiState<'_, WindowsOs<Driver>>, address: Va, ) -> Result<bool, VmiError>
Checks if a given address is a valid user-mode address.
This method determines whether the provided address falls within the range of valid user-mode addresses in Windows.
Sourcepub fn unloaded_modules<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<impl Iterator<Item = Result<WindowsUnloadedDriver<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
pub fn unloaded_modules<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<impl Iterator<Item = Result<WindowsUnloadedDriver<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over recently unloaded drivers.
Walks the kernel’s fixed-size circular buffer of unloaded driver records, newest first. The iterator stops at the first empty slot or after the buffer’s 50-entry capacity has been visited.
§Implementation Details
Corresponds to MmUnloadedDrivers and MmLastUnloadedDriver.
Sourcepub fn number_of_processors(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<u16, VmiError>
pub fn number_of_processors( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<u16, VmiError>
Returns the number of active processors in the system.
§Implementation Details
Corresponds to KeNumberProcessors.
Sourcepub fn current_kpcr(vmi: VmiState<'_, WindowsOs<Driver>>) -> Va
pub fn current_kpcr(vmi: VmiState<'_, WindowsOs<Driver>>) -> Va
Returns the virtual address of the current Kernel Processor Control Region (KPCR).
The KPCR is a per-processor data structure in Windows that contains critical information about the current processor state. This method returns the virtual address of the KPCR for the current processor.
Sourcepub fn kprcb<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
vcpu_id: VcpuId,
) -> Result<WindowsKernelProcessorBlock<'a, Driver>, VmiError>
pub fn kprcb<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, vcpu_id: VcpuId, ) -> Result<WindowsKernelProcessorBlock<'a, Driver>, VmiError>
Returns a Kernel Processor Control Block (KPRCB) for the specified processor.
The KPRCB is an opaque, per-processor structure embedded within the KPCR.
§Implementation Details
Corresponds to KiProcessorBlock symbol, offset by the processor ID.
Sourcepub fn current_kprcb<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<WindowsKernelProcessorBlock<'a, Driver>, VmiError>
pub fn current_kprcb<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<WindowsKernelProcessorBlock<'a, Driver>, VmiError>
Returns the Kernel Processor Control Block (KPRCB) for the processor whose register state is currently loaded.
Unlike kprcb, which indexes the KiProcessorBlock
array by processor ID, this resolves the PRCB from the current KPCR
(gs-relative on AMD64) through KPCR.Prcb.
§Implementation Details
Corresponds to KPCR.Prcb.
Sourcepub fn exception_record(
vmi: VmiState<'_, WindowsOs<Driver>>,
address: Va,
) -> Result<WindowsExceptionRecord, VmiError>
pub fn exception_record( vmi: VmiState<'_, WindowsOs<Driver>>, address: Va, ) -> Result<WindowsExceptionRecord, VmiError>
Returns information from an exception record at the specified address.
This method reads and parses an EXCEPTION_RECORD structure from
memory, providing detailed information about an exception that has
occurred in the system. The returned WindowsExceptionRecord
contains data such as the exception code, flags, and related memory
addresses.
Sourcepub fn last_status(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<Option<u32>, VmiError>
pub fn last_status( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<Option<u32>, VmiError>
Returns the last status value for the current thread.
In Windows, the last status value is typically used to store error codes or success indicators from system calls. This method reads this value from the Thread Environment Block (TEB) of the current thread, providing insight into the outcome of recent operations performed by the thread.
Returns None if the TEB is not available.
§Notes
LastStatusValue is a NTSTATUS value, whereas LastError is a Win32
error code. The two values are related but not identical. You can obtain
the Win32 error code by calling
VmiOs::last_error.
§Implementation Details
Corresponds to NtCurrentTeb()->LastStatusValue.
Sourcepub fn idle_process<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<WindowsProcess<'a, Driver>, VmiError>
pub fn idle_process<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<WindowsProcess<'a, Driver>, VmiError>
Sourcepub fn idle_thread<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<WindowsThread<'a, Driver>, VmiError>
pub fn idle_thread<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<WindowsThread<'a, Driver>, VmiError>
Returns the idle thread for the current processor.
The idle thread is a per-processor thread that runs when no other threads are scheduled on that processor.
§Implementation Details
Corresponds to KPCR.Prcb.IdleThread.
Sourcepub fn object<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
va: Va,
) -> Result<WindowsObject<'a, Driver>, VmiError>
pub fn object<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, ) -> Result<WindowsObject<'a, Driver>, VmiError>
Returns the Windows object.
Sourcepub fn object_type<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
kind: WindowsObjectTypeKind,
) -> Result<WindowsObjectType<'a, Driver>, VmiError>
pub fn object_type<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, kind: WindowsObjectTypeKind, ) -> Result<WindowsObjectType<'a, Driver>, VmiError>
Returns a Windows object type for the given object kind.
§Notes
The object type is cached after the first read.
§Implementation Details
Filecorresponds toIoFileObjectType.Jobcorresponds toPsJobType.Keycorresponds toCmKeyObjectType.Processcorresponds toPsProcessType.Threadcorresponds toPsThreadType.Tokencorresponds toSeTokenObjectType.- Other types are not supported.
Sourcepub fn object_root_directory<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<WindowsDirectoryObject<'a, Driver>, VmiError>
pub fn object_root_directory<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<WindowsDirectoryObject<'a, Driver>, VmiError>
Returns the object header cookie used for obfuscating object types.
Returns None if the cookie is not present in the kernel image.
§Notes
Windows 10 introduced a security feature that obfuscates the type
of kernel objects by XORing the TypeIndex field in the object header
with a random cookie value. This method fetches that cookie, which is
essential for correctly interpreting object headers in memory.
The cookie is cached after the first read.
§Implementation Details
Corresponds to ObHeaderCookie symbol.
Sourcepub fn object_attributes<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
object_attributes: Va,
) -> Result<WindowsObjectAttributes<'a, Driver>, VmiError>
pub fn object_attributes<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, object_attributes: Va, ) -> Result<WindowsObjectAttributes<'a, Driver>, VmiError>
Returns the Windows object attributes.
Sourcepub fn lookup_object<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
path: impl AsRef<str>,
) -> Result<Option<WindowsObject<'a, Driver>>, VmiError>
pub fn lookup_object<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, path: impl AsRef<str>, ) -> Result<Option<WindowsObject<'a, Driver>>, VmiError>
Resolves an absolute object-namespace path to a named object.
Descends from the root directory (object_root_directory) one
component at a time.
Returns Ok(None) when a component does not exist, or when an
intermediate component resolves to something other than a
Directory. The final component may be any object type.
Does not follow SymbolicLink objects.
Sourcepub fn hives<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<impl Iterator<Item = Result<WindowsHive<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
pub fn hives<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<impl Iterator<Item = Result<WindowsHive<'a, Driver>, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over all loaded registry hives.
This method returns an iterator over all loaded registry hives. It
reads the CmpHiveListHead symbol from the kernel image and iterates
over the linked list of _CMHIVE structures representing each hive.
Sourcepub fn lookup_key<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
path: impl AsRef<str>,
) -> Result<Option<WindowsKeyNode<'a, Driver>>, VmiError>
pub fn lookup_key<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, path: impl AsRef<str>, ) -> Result<Option<WindowsKeyNode<'a, Driver>>, VmiError>
Resolves an absolute registry path against the loaded hive set.
Picks the hive whose HiveRootPath is the longest component-aligned
case-insensitive prefix of path, strips that prefix, and forwards
the remainder to WindowsHive::lookup.
Returns Ok(None) when no hive root prefixes the path or when the
descent does not find the key.
Hives with an empty HiveRootPath match any input at depth zero,
so they only win when no loaded hive owns a real prefix.
Does not follow HIVE_EXIT links into other hives.
Sourcepub fn read_fast_ref(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Va, VmiError>
pub fn read_fast_ref( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Va, VmiError>
Reads an _EX_FAST_REF and returns the referenced object’s
virtual address, with the low reference-count bits masked off.
Sourcepub fn read_ansi_string_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from an _ANSI_STRING structure.
This method reads a native _ANSI_STRING structure which contains
an ASCII/ANSI string. The structure is read according to the current
OS’s architecture (32-bit or 64-bit).
Sourcepub fn read_ansi_string32_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string32_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from a 32-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_ansi_string64_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string64_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from a 64-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
64-bit processes where pointers are 64 bits.
Sourcepub fn read_ansi_string(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_ansi_string( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from an _ANSI_STRING structure.
This method reads a native _ANSI_STRING structure which contains
an ASCII/ANSI string. The structure is read according to the current
OS’s architecture (32-bit or 64-bit).
Sourcepub fn read_ansi_string32(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_ansi_string32( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from a 32-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_ansi_string64(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_ansi_string64( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from a 64-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
64-bit processes where pointers are 64 bits.
Sourcepub fn read_unicode_string_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u16>, VmiError>
Reads string from a _UNICODE_STRING structure.
This method reads a native _UNICODE_STRING structure which contains
a UTF-16 string. The structure is read according to the current OS’s
architecture (32-bit or 64-bit).
Sourcepub fn read_unicode_string32_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string32_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u16>, VmiError>
Reads string from a 32-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_unicode_string64_bytes(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string64_bytes( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<Vec<u16>, VmiError>
Reads string from a 64-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 64-bit processes where pointers are 64 bits.
Sourcepub fn read_unicode_string(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_unicode_string( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from a _UNICODE_STRING structure.
This method reads a native _UNICODE_STRING structure which contains
a UTF-16 string. The structure is read according to the current OS’s
architecture (32-bit or 64-bit).
Sourcepub fn read_unicode_string32(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_unicode_string32( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from a 32-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_unicode_string64(
vmi: VmiState<'_, WindowsOs<Driver>>,
va: Va,
) -> Result<String, VmiError>
pub fn read_unicode_string64( vmi: VmiState<'_, WindowsOs<Driver>>, va: Va, ) -> Result<String, VmiError>
Reads string from a 64-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 64-bit processes where pointers are 64 bits.
Sourcepub fn read_ansi_string_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from an _ANSI_STRING structure.
This method reads a native _ANSI_STRING structure which contains
an ASCII/ANSI string. The structure is read according to the current
OS’s architecture (32-bit or 64-bit).
Sourcepub fn read_ansi_string32_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string32_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from a 32-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_ansi_string64_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u8>, VmiError>
pub fn read_ansi_string64_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u8>, VmiError>
Reads string of bytes from a 64-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
64-bit processes where pointers are 64 bits.
Sourcepub fn read_ansi_string_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_ansi_string_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from an _ANSI_STRING structure.
This method reads a native _ANSI_STRING structure which contains
an ASCII/ANSI string. The structure is read according to the current
OS’s architecture (32-bit or 64-bit).
Sourcepub fn read_ansi_string32_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_ansi_string32_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from a 32-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_ansi_string64_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_ansi_string64_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from a 64-bit version of _ANSI_STRING structure.
This method is specifically for reading _ANSI_STRING structures in
64-bit processes where pointers are 64 bits.
Sourcepub fn read_unicode_string_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u16>, VmiError>
Reads string from a _UNICODE_STRING structure.
This method reads a native _UNICODE_STRING structure which contains
a UTF-16 string. The structure is read according to the current OS’s
architecture (32-bit or 64-bit).
Sourcepub fn read_unicode_string32_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string32_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u16>, VmiError>
Reads string from a 32-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_unicode_string64_bytes_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<Vec<u16>, VmiError>
pub fn read_unicode_string64_bytes_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<Vec<u16>, VmiError>
Reads string from a 64-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 64-bit processes where pointers are 64 bits.
Sourcepub fn read_unicode_string_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_unicode_string_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from a _UNICODE_STRING structure.
This method reads a native _UNICODE_STRING structure which contains
a UTF-16 string. The structure is read according to the current OS’s
architecture (32-bit or 64-bit).
Sourcepub fn read_unicode_string32_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_unicode_string32_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from a 32-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 32-bit processes or WoW64 processes where pointers are 32 bits.
Sourcepub fn read_unicode_string64_in(
vmi: VmiState<'_, WindowsOs<Driver>>,
ctx: impl Into<AccessContext>,
) -> Result<String, VmiError>
pub fn read_unicode_string64_in( vmi: VmiState<'_, WindowsOs<Driver>>, ctx: impl Into<AccessContext>, ) -> Result<String, VmiError>
Reads string from a 64-bit version of _UNICODE_STRING structure.
This method is specifically for reading _UNICODE_STRING structures
in 64-bit processes where pointers are 64 bits.
Sourcepub fn linked_list<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
list_head: Va,
offset: u64,
) -> Result<impl Iterator<Item = Result<Va, VmiError>> + use<'a, Driver>, VmiError>
pub fn linked_list<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, list_head: Va, offset: u64, ) -> Result<impl Iterator<Item = Result<Va, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over a doubly-linked list of LIST_ENTRY structures.
This method is used to iterate over a doubly-linked list of LIST_ENTRY
structures in memory. It returns an iterator that yields the virtual
addresses of each LIST_ENTRY structure in the list.
Trait Implementations§
Source§impl<Driver, T, Bridge> InjectorExecutionAdapter<KernelMode, T, Bridge> for WindowsOs<Driver>where
Driver: VmiDriver<Architecture = Amd64> + VmiRead + VmiWrite + VmiSetProtection + VmiQueryRegisters + VmiEventControl + VmiViewControl + VmiVmControl,
Bridge: BridgeDispatch<WindowsOs<Driver>, u64>,
impl<Driver, T, Bridge> InjectorExecutionAdapter<KernelMode, T, Bridge> for WindowsOs<Driver>where
Driver: VmiDriver<Architecture = Amd64> + VmiRead + VmiWrite + VmiSetProtection + VmiQueryRegisters + VmiEventControl + VmiViewControl + VmiVmControl,
Bridge: BridgeDispatch<WindowsOs<Driver>, u64>,
Source§impl<Driver, T, Bridge> InjectorExecutionAdapter<UserMode, T, Bridge> for WindowsOs<Driver>where
Driver: VmiDriver<Architecture = Amd64> + VmiRead + VmiWrite + VmiSetProtection + VmiEventControl + VmiViewControl + VmiVmControl,
Bridge: BridgeDispatch<WindowsOs<Driver>, u64>,
impl<Driver, T, Bridge> InjectorExecutionAdapter<UserMode, T, Bridge> for WindowsOs<Driver>where
Driver: VmiDriver<Architecture = Amd64> + VmiRead + VmiWrite + VmiSetProtection + VmiEventControl + VmiViewControl + VmiVmControl,
Bridge: BridgeDispatch<WindowsOs<Driver>, u64>,
Source§impl<Driver> OsAdapter for WindowsOs<Driver>where
Driver: VmiRead,
<Driver as VmiDriver>::Architecture: ArchAdapter<Driver> + ArchAdapter<Driver>,
impl<Driver> OsAdapter for WindowsOs<Driver>where
Driver: VmiRead,
<Driver as VmiDriver>::Architecture: ArchAdapter<Driver> + ArchAdapter<Driver>,
Source§type DebugSignature = CodeView
type DebugSignature = CodeView
Source§fn resolve_kernel_module(
vmi: &VmiState<'_, WindowsOs<Driver>>,
isr: &IsrCache,
name: &str,
) -> Result<Option<Resolved<WindowsOs<Driver>>>, VmiError>
fn resolve_kernel_module( vmi: &VmiState<'_, WindowsOs<Driver>>, isr: &IsrCache, name: &str, ) -> Result<Option<Resolved<WindowsOs<Driver>>>, VmiError>
Source§fn resolve_user_module(
vmi: &VmiState<'_, WindowsOs<Driver>>,
isr: &IsrCache,
name: &str,
process: impl ProcessPredicate<WindowsOs<Driver>>,
) -> Result<Option<Resolved<WindowsOs<Driver>>>, VmiError>
fn resolve_user_module( vmi: &VmiState<'_, WindowsOs<Driver>>, isr: &IsrCache, name: &str, process: impl ProcessPredicate<WindowsOs<Driver>>, ) -> Result<Option<Resolved<WindowsOs<Driver>>>, VmiError>
resolve_user_module.Source§impl<Driver, Handler> VmiHandler<WindowsOs<Driver>> for Reactor<WindowsOs<Driver>, Handler>where
Driver: VmiFullDriver<Architecture = Amd64>,
Handler: ReactorHandler<WindowsOs<Driver>>,
<<Handler as ReactorHandler<WindowsOs<Driver>>>::Event as ReactorEvent>::Module: ReactorModule<WindowsOs<Driver>>,
impl<Driver, Handler> VmiHandler<WindowsOs<Driver>> for Reactor<WindowsOs<Driver>, Handler>where
Driver: VmiFullDriver<Architecture = Amd64>,
Handler: ReactorHandler<WindowsOs<Driver>>,
<<Handler as ReactorHandler<WindowsOs<Driver>>>::Event as ReactorEvent>::Module: ReactorModule<WindowsOs<Driver>>,
Source§type Output = Option<<Handler as ReactorHandler<WindowsOs<Driver>>>::Output>
type Output = Option<<Handler as ReactorHandler<WindowsOs<Driver>>>::Output>
Source§fn handle_event(
&mut self,
vmi: VmiContext<'_, WindowsOs<Driver>>,
) -> VmiEventResponse<<Driver as VmiDriver>::Architecture>
fn handle_event( &mut self, vmi: VmiContext<'_, WindowsOs<Driver>>, ) -> VmiEventResponse<<Driver as VmiDriver>::Architecture>
Source§fn cleanup(&mut self, vmi: &VmiSession<'_, WindowsOs<Driver>>)
fn cleanup(&mut self, vmi: &VmiSession<'_, WindowsOs<Driver>>)
Source§fn poll(
&self,
) -> Option<<Reactor<WindowsOs<Driver>, Handler> as VmiHandler<WindowsOs<Driver>>>::Output>
fn poll( &self, ) -> Option<<Reactor<WindowsOs<Driver>, Handler> as VmiHandler<WindowsOs<Driver>>>::Output>
Source§fn handle_timeout(&mut self, _session: &VmiSession<'_, Os>)
fn handle_timeout(&mut self, _session: &VmiSession<'_, Os>)
Source§fn handle_interrupted(&mut self, _session: &VmiSession<'_, Os>)
fn handle_interrupted(&mut self, _session: &VmiSession<'_, Os>)
Source§impl<Driver> VmiOs for WindowsOs<Driver>
impl<Driver> VmiOs for WindowsOs<Driver>
Source§fn kpti_enabled(vmi: VmiState<'_, WindowsOs<Driver>>) -> Result<bool, VmiError>
fn kpti_enabled(vmi: VmiState<'_, WindowsOs<Driver>>) -> Result<bool, VmiError>
Checks if Kernel Virtual Address Shadow (KVA Shadow) is enabled.
KVA Shadow is a security feature introduced in Windows 10 that mitigates Meltdown and Spectre vulnerabilities by isolating kernel memory from user-mode processes.
§Notes
This value is cached after the first read.
§Implementation Details
Corresponds to KiKvaShadow symbol.
Source§fn modules<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<impl Iterator<Item = Result<<WindowsOs<Driver> as VmiOs>::Module<'a>, VmiError>> + use<'a, Driver>, VmiError>
fn modules<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<impl Iterator<Item = Result<<WindowsOs<Driver> as VmiOs>::Module<'a>, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over all loaded Windows Driver modules.
This method returns an iterator over all loaded Windows Driver modules.
It reads the PsLoadedModuleList symbol from the kernel image and
iterates over the linked list of KLDR_DATA_TABLE_ENTRY structures
representing each loaded module.
Source§fn processes<'a>(
vmi: VmiState<'a, WindowsOs<Driver>>,
) -> Result<impl Iterator<Item = Result<<WindowsOs<Driver> as VmiOs>::Process<'a>, VmiError>> + use<'a, Driver>, VmiError>
fn processes<'a>( vmi: VmiState<'a, WindowsOs<Driver>>, ) -> Result<impl Iterator<Item = Result<<WindowsOs<Driver> as VmiOs>::Process<'a>, VmiError>> + use<'a, Driver>, VmiError>
Returns an iterator over all Windows processes.
This method returns an iterator over all Windows processes. It reads the
PsActiveProcessHead symbol from the kernel image and iterates over the
linked list of EPROCESS structures representing each process.
Source§fn current_process(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
fn current_process( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
Returns the current process.
Source§fn system_process(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
fn system_process( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
Returns the system process.
The system process is the first process created by the Windows kernel during system initialization. It is the parent process of all other processes in the system.
Source§fn current_thread(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<<WindowsOs<Driver> as VmiOs>::Thread<'_>, VmiError>
fn current_thread( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<<WindowsOs<Driver> as VmiOs>::Thread<'_>, VmiError>
Returns the current thread.
Source§type Architecture = <Driver as VmiDriver>::Architecture
type Architecture = <Driver as VmiDriver>::Architecture
Source§type Process<'a> = WindowsProcess<'a, Driver>
type Process<'a> = WindowsProcess<'a, Driver>
Source§type Thread<'a> = WindowsThread<'a, Driver>
type Thread<'a> = WindowsThread<'a, Driver>
Source§type Image<'a> = WindowsImage<'a, Driver>
type Image<'a> = WindowsImage<'a, Driver>
Source§type Module<'a> = WindowsModule<'a, Driver>
type Module<'a> = WindowsModule<'a, Driver>
Source§type UserModule<'a> = WindowsUserModule<'a, Driver>
type UserModule<'a> = WindowsUserModule<'a, Driver>
Source§type Region<'a> = WindowsRegion<'a, Driver>
type Region<'a> = WindowsRegion<'a, Driver>
Source§type Mapped<'a> = WindowsControlArea<'a, Driver>
type Mapped<'a> = WindowsControlArea<'a, Driver>
Source§fn kernel_image_base(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<Va, VmiError>
fn kernel_image_base( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<Va, VmiError>
Source§fn kernel_information_string(
vmi: VmiState<'_, WindowsOs<Driver>>,
) -> Result<String, VmiError>
fn kernel_information_string( vmi: VmiState<'_, WindowsOs<Driver>>, ) -> Result<String, VmiError>
Source§fn process(
vmi: VmiState<'_, WindowsOs<Driver>>,
process: ProcessObject,
) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
fn process( vmi: VmiState<'_, WindowsOs<Driver>>, process: ProcessObject, ) -> Result<<WindowsOs<Driver> as VmiOs>::Process<'_>, VmiError>
Source§fn thread(
vmi: VmiState<'_, WindowsOs<Driver>>,
thread: ThreadObject,
) -> Result<<WindowsOs<Driver> as VmiOs>::Thread<'_>, VmiError>
fn thread( vmi: VmiState<'_, WindowsOs<Driver>>, thread: ThreadObject, ) -> Result<<WindowsOs<Driver> as VmiOs>::Thread<'_>, VmiError>
Source§fn image(
vmi: VmiState<'_, WindowsOs<Driver>>,
image_base: Va,
) -> Result<<WindowsOs<Driver> as VmiOs>::Image<'_>, VmiError>
fn image( vmi: VmiState<'_, WindowsOs<Driver>>, image_base: Va, ) -> Result<<WindowsOs<Driver> as VmiOs>::Image<'_>, VmiError>
Source§fn module(
vmi: VmiState<'_, WindowsOs<Driver>>,
module: Va,
) -> Result<<WindowsOs<Driver> as VmiOs>::Module<'_>, VmiError>
fn module( vmi: VmiState<'_, WindowsOs<Driver>>, module: Va, ) -> Result<<WindowsOs<Driver> as VmiOs>::Module<'_>, VmiError>
Source§fn user_module(
vmi: VmiState<'_, WindowsOs<Driver>>,
module: Va,
root: Pa,
) -> Result<<WindowsOs<Driver> as VmiOs>::UserModule<'_>, VmiError>
fn user_module( vmi: VmiState<'_, WindowsOs<Driver>>, module: Va, root: Pa, ) -> Result<<WindowsOs<Driver> as VmiOs>::UserModule<'_>, VmiError>
Source§fn region(
vmi: VmiState<'_, WindowsOs<Driver>>,
region: Va,
) -> Result<<WindowsOs<Driver> as VmiOs>::Region<'_>, VmiError>
fn region( vmi: VmiState<'_, WindowsOs<Driver>>, region: Va, ) -> Result<<WindowsOs<Driver> as VmiOs>::Region<'_>, VmiError>
Source§fn syscall_argument(
vmi: VmiState<'_, WindowsOs<Driver>>,
index: u64,
) -> Result<u64, VmiError>
fn syscall_argument( vmi: VmiState<'_, WindowsOs<Driver>>, index: u64, ) -> Result<u64, VmiError>
Source§fn function_argument(
vmi: VmiState<'_, WindowsOs<Driver>>,
index: u64,
) -> Result<u64, VmiError>
fn function_argument( vmi: VmiState<'_, WindowsOs<Driver>>, index: u64, ) -> Result<u64, VmiError>
Auto Trait Implementations§
impl<Driver> !Freeze for WindowsOs<Driver>
impl<Driver> !RefUnwindSafe for WindowsOs<Driver>
impl<Driver> !Sync for WindowsOs<Driver>
impl<Driver> Send for WindowsOs<Driver>where
Driver: Send,
impl<Driver> Unpin for WindowsOs<Driver>where
Driver: Unpin,
impl<Driver> UnsafeUnpin for WindowsOs<Driver>
impl<Driver> UnwindSafe for WindowsOs<Driver>where
Driver: UnwindSafe,
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> VmiOsExt for Twhere
T: VmiOs,
impl<T> VmiOsExt for Twhere
T: VmiOs,
Source§fn find_process<'a>(
vmi: VmiState<'a, Self>,
predicate: impl ProcessPredicate<Self>,
) -> Result<Option<Self::Process<'a>>, VmiError>
fn find_process<'a>( vmi: VmiState<'a, Self>, predicate: impl ProcessPredicate<Self>, ) -> Result<Option<Self::Process<'a>>, VmiError>
predicate, or Ok(None)
if no live process matches.Source§fn filter_processes<'a>(
vmi: VmiState<'a, Self>,
predicate: impl ProcessPredicate<Self>,
) -> Result<impl Iterator<Item = Result<Self::Process<'a>, VmiError>>, VmiError>
fn filter_processes<'a>( vmi: VmiState<'a, Self>, predicate: impl ProcessPredicate<Self>, ) -> Result<impl Iterator<Item = Result<Self::Process<'a>, VmiError>>, VmiError>
predicate.Source§fn find_module<'a>(
vmi: VmiState<'a, Self>,
predicate: impl ModulePredicate<Self>,
) -> Result<Option<Self::Module<'a>>, VmiError>
fn find_module<'a>( vmi: VmiState<'a, Self>, predicate: impl ModulePredicate<Self>, ) -> Result<Option<Self::Module<'a>>, VmiError>
predicate, or
Ok(None) if no loaded module matches.