vmi_utils/injector/mod.rs
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
//! Code injection functionality.
//!
//! This module provides mechanisms for injecting and executing code in
//! a running process or kernel. It handles thread hijacking, code execution
//! monitoring, and cleanup. The injection process is defined using recipes -
//! declarative sequences of steps that specify what code to inject and how to
//! execute it.
//!
//! # Limitations
//!
//! The injector currently only supports Windows OS and AMD64 architecture.
//! Injections into 32-bit processes are not currently supported.
//!
//! # Examples
//!
//! Inject a `MessageBox()` call into a running process:
//!
//! ```no_run
//! use vmi::{
//! arch::amd64::Amd64,
//! os::windows::WindowsOs,
//! utils::injector::{recipe, InjectorHandler, Recipe},
//! VcpuId, VmiDriver, VmiSession,
//! };
//!
//! struct MessageBox {
//! caption: String,
//! text: String,
//! }
//!
//! impl MessageBox {
//! pub fn new(caption: impl AsRef<str>, text: impl AsRef<str>) -> Self {
//! Self {
//! caption: caption.as_ref().to_string(),
//! text: text.as_ref().to_string(),
//! }
//! }
//! }
//!
//! fn recipe_factory<Driver>(data: MessageBox) -> Recipe<Driver, WindowsOs<Driver>, MessageBox>
//! where
//! Driver: VmiDriver<Architecture = Amd64>,
//! {
//! recipe![
//! Recipe::<_, WindowsOs<Driver>, _>::new(data),
//! {
//! inj! {
//! user32!MessageBoxA(
//! 0, // hWnd
//! data![text], // lpText
//! data![caption], // lpCaption
//! 0 // uType
//! )
//! }
//! }
//! ]
//! }
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # use vmi::driver::xen::VmiXenDriver;
//! # let vmi: VmiSession<VmiXenDriver<Amd64>, WindowsOs<VmiXenDriver<Amd64>>> = unimplemented!();
//! # let profile = unimplemented!();
//! # let pid = unimplemented!();
//! #
//! // Create and execute the injection handler
//! vmi.handle(|vmi| {
//! InjectorHandler::new(
//! vmi,
//! &profile,
//! pid,
//! recipe_factory(MessageBox::new(
//! "Hello from VMI",
//! "Injected message box!"
//! )),
//! )
//! })?;
//! #
//! # Ok(())
//! # }
//! ```
use vmi_core::{
os::{ProcessId, ThreadId, VmiOs},
Pa, Va, View, VmiDriver,
};
mod arch;
pub use self::arch::ArchAdapter;
mod os;
pub use self::os::OsAdapter;
mod argument;
pub use self::argument::{Argument, ArgumentData};
mod call;
pub use self::call::CallBuilder;
#[doc(hidden)]
pub mod macros;
#[doc(inline)]
pub use crate::_private_recipe as recipe;
mod recipe;
pub use self::recipe::{
ImageSymbolCache, Recipe, RecipeContext, RecipeControlFlow, RecipeExecutor,
};
/// A handler for managing code injection into a running system.
///
/// The handler monitors CPU events to hijack threads, inject code, and track execution.
/// It uses recipes to define the injection sequence and maintains state about the
/// injection process.
pub struct InjectorHandler<Driver, Os, T>
where
Driver: VmiDriver,
Os: VmiOs<Driver> + OsAdapter<Driver>,
{
/// Process ID being injected into.
pub(super) pid: ProcessId,
/// Thread ID that was hijacked for injection.
pub(super) tid: Option<ThreadId>,
/// Whether a thread has been successfully hijacked.
pub(super) hijacked: bool,
/// Virtual address of the stack in the hijacked thread.
pub(super) sp_va: Option<Va>,
/// Virtual address of the instruction pointer in the hijacked thread.
pub(super) ip_va: Option<Va>,
/// Physical address of the instruction pointer in the hijacked thread.
pub(super) ip_pa: Option<Pa>,
/// OS-specific offsets for accessing kernel structures.
pub(super) offsets: <Os as OsAdapter<Driver>>::Offsets,
/// Executor for running the injection recipe.
pub(super) recipe: RecipeExecutor<Driver, Os, T>,
/// Memory view used for injection operations.
pub(super) view: View,
/// Whether the bridge has been created.
pub(super) bridge: bool,
/// Whether the injection has completed.
pub(super) finished: bool,
}