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}