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,
}