vmi_utils/injector/
mod.rs

1//! Code injection functionality.
2//!
3//! This module provides mechanisms for injecting and executing code in
4//! a running process or kernel. It handles thread hijacking, code execution
5//! monitoring, and cleanup. The injection process is defined using recipes -
6//! declarative sequences of steps that specify what code to inject and how to
7//! execute it.
8//!
9//! # Limitations
10//!
11//! The injector currently only supports Windows OS and AMD64 architecture.
12//! Injections into 32-bit processes are not currently supported.
13//!
14//! # Examples
15//!
16//!  Inject a `MessageBox()` call into a running process:
17//!
18//! ```no_run
19//! use vmi::{
20//!     arch::amd64::Amd64,
21//!     os::windows::WindowsOs,
22//!     utils::injector::{recipe, InjectorHandler, Recipe},
23//!     VcpuId, VmiDriver, VmiSession,
24//! };
25//!
26//! struct MessageBox {
27//!     caption: String,
28//!     text: String,
29//! }
30//!
31//! impl MessageBox {
32//!     pub fn new(caption: impl AsRef<str>, text: impl AsRef<str>) -> Self {
33//!         Self {
34//!             caption: caption.as_ref().to_string(),
35//!             text: text.as_ref().to_string(),
36//!         }
37//!     }
38//! }
39//!
40//! fn recipe_factory<Driver>(data: MessageBox) -> Recipe<Driver, WindowsOs<Driver>, MessageBox>
41//! where
42//!     Driver: VmiDriver<Architecture = Amd64>,
43//! {
44//!     recipe![
45//!         Recipe::<_, WindowsOs<Driver>, _>::new(data),
46//!         {
47//!             inj! {
48//!                 user32!MessageBoxA(
49//!                     0,                          // hWnd
50//!                     data![text],                // lpText
51//!                     data![caption],             // lpCaption
52//!                     0                           // uType
53//!                 )
54//!             }
55//!         }
56//!     ]
57//! }
58//!
59//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
60//! # use vmi::driver::xen::VmiXenDriver;
61//! # let vmi: VmiSession<VmiXenDriver<Amd64>, WindowsOs<VmiXenDriver<Amd64>>> = unimplemented!();
62//! # let profile = unimplemented!();
63//! # let pid = unimplemented!();
64//! #
65//! // Create and execute the injection handler
66//! vmi.handle(|vmi| {
67//!     InjectorHandler::new(
68//!         vmi,
69//!         &profile,
70//!         pid,
71//!         recipe_factory(MessageBox::new(
72//!             "Hello from VMI",
73//!             "Injected message box!"
74//!         )),
75//!     )
76//! })?;
77//! #
78//! # Ok(())
79//! # }
80//! ```
81
82use vmi_core::{
83    Pa, Va, View, VmiDriver,
84    os::{ProcessId, ThreadId, VmiOs},
85};
86
87mod arch;
88pub use self::arch::ArchAdapter;
89
90mod os;
91pub use self::os::OsAdapter;
92
93mod argument;
94pub use self::argument::{Argument, ArgumentData};
95
96mod call;
97pub use self::call::CallBuilder;
98
99#[doc(hidden)]
100pub mod macros;
101#[doc(inline)]
102pub use crate::_private_recipe as recipe;
103use crate::bridge::{BridgeHandler, BridgePacket};
104
105mod recipe;
106pub use self::recipe::{
107    ImageSymbolCache, Recipe, RecipeContext, RecipeControlFlow, RecipeExecutor,
108};
109
110/// Result code for the injector.
111pub type InjectorResultCode = u64;
112
113/// A handler for managing code injection into a running system.
114///
115/// The handler monitors CPU events to hijack threads, inject code, and track execution.
116/// It uses recipes to define the injection sequence and maintains state about the
117/// injection process.
118pub struct InjectorHandler<Driver, Os, T, Bridge = ()>
119where
120    Driver: VmiDriver,
121    Os: VmiOs<Driver> + OsAdapter<Driver>,
122    Bridge: BridgeHandler<Driver, Os, InjectorResultCode>,
123{
124    /// Process ID being injected into.
125    pub(super) pid: ProcessId,
126
127    /// Thread ID that was hijacked for injection.
128    pub(super) tid: Option<ThreadId>,
129
130    /// Whether a thread has been successfully hijacked.
131    pub(super) hijacked: bool,
132
133    /// Virtual address of the instruction pointer in the hijacked thread.
134    pub(super) ip_va: Option<Va>,
135
136    /// Physical address of the instruction pointer in the hijacked thread.
137    pub(super) ip_pa: Option<Pa>,
138
139    /// OS-specific offsets for accessing kernel structures.
140    pub(super) offsets: <Os as OsAdapter<Driver>>::Offsets,
141
142    /// Executor for running the injection recipe.
143    pub(super) recipe: RecipeExecutor<Driver, Os, T>,
144
145    /// Memory view used for injection operations.
146    pub(super) view: View,
147
148    /// Bridge.
149    pub(super) bridge: Bridge,
150
151    /// Whether the injection has completed.
152    pub(super) finished: Option<Result<InjectorResultCode, BridgePacket>>,
153}