vmi_core/os/
mod.rs

1#![doc = include_str!("../../docs/os.md")]
2
3mod dummy;
4mod image;
5mod mapped;
6mod module;
7mod process;
8mod region;
9mod struct_reader;
10mod thread;
11
12use vmi_macros::derive_os_wrapper;
13
14pub use self::{
15    dummy::NoOS,
16    image::{VmiOsImage, VmiOsImageArchitecture, VmiOsImageSymbol},
17    mapped::VmiOsMapped,
18    module::VmiOsModule,
19    process::{ProcessId, ProcessObject, VmiOsProcess},
20    region::{VmiOsRegion, VmiOsRegionKind},
21    struct_reader::StructReader,
22    thread::{ThreadId, ThreadObject, VmiOsThread},
23};
24use crate::{Va, VmiDriver, VmiError, VmiOsState, VmiState};
25
26/// Operating system trait.
27#[derive_os_wrapper(VmiOsState)]
28pub trait VmiOs<Driver>: Sized
29where
30    Driver: VmiDriver,
31{
32    /// The process type.
33    type Process<'a>: VmiOsProcess<'a, Driver> + 'a
34    where
35        Self: 'a;
36
37    /// The thread type.
38    type Thread<'a>: VmiOsThread<'a, Driver> + 'a
39    where
40        Self: 'a;
41
42    /// The image type.
43    type Image<'a>: VmiOsImage<'a, Driver> + 'a
44    where
45        Self: 'a;
46
47    /// The kernel module type.
48    type Module<'a>: VmiOsModule<'a, Driver> + 'a
49    where
50        Self: 'a;
51
52    /// The memory region type.
53    type Region<'a>: VmiOsRegion<'a, Driver> + 'a
54    where
55        Self: 'a;
56
57    /// The memory mapped region type.
58    type Mapped<'a>: VmiOsMapped<'a, Driver> + 'a
59    where
60        Self: 'a;
61
62    /// Retrieves the base address of the kernel image.
63    ///
64    /// The kernel image base address is usually found using some special
65    /// CPU register - for example, a register that contains the address of
66    /// the system call handler. Such register is set by the operating system
67    /// during boot and is left unchanged (unless some rootkits are involved).
68    ///
69    /// Therefore, this function can accept the CPU registers from any point
70    /// of the VM execution (except for the early boot stage).
71    ///
72    /// For catching the exact moment when the kernel image base address is
73    /// set, you can monitor the `MSR_LSTAR` register (on AMD64) for writes.
74    ///
75    /// # Architecture-specific
76    ///
77    /// - **AMD64**: The kernel image base address is usually found using the
78    ///   `MSR_LSTAR` register.
79    ///
80    /// # Notes
81    ///
82    /// A malicious code (such as a rootkit) could modify values of the
83    /// registers, so the returned value might not be accurate.
84    fn kernel_image_base(vmi: VmiState<Driver, Self>) -> Result<Va, VmiError>;
85
86    /// Retrieves an implementation-specific string containing kernel
87    /// information.
88    ///
89    /// # Platform-specific
90    ///
91    /// - **Windows**: Retrieves the `NtBuildLab` string from the kernel image.
92    /// - **Linux**: Retrieves the `linux_banner` string from the kernel image.
93    fn kernel_information_string(vmi: VmiState<Driver, Self>) -> Result<String, VmiError>;
94
95    /// Checks if Kernel Page Table Isolation (KPTI) is enabled.
96    ///
97    /// # Platform-specific
98    ///
99    /// - **Windows**: Retrieves the `KiKvaShadow` global variable, if it exists.
100    fn kpti_enabled(vmi: VmiState<Driver, Self>) -> Result<bool, VmiError>;
101
102    /// Returns an iterator over the loaded kernel modules.
103    ///
104    /// # Platform-specific
105    ///
106    /// - **Windows**: Retrieves information from the `PsLoadedModuleList`.
107    /// - **Linux**: Retrieves information from the `modules` list.
108    fn modules<'a>(
109        vmi: VmiState<'a, Driver, Self>,
110    ) -> Result<impl Iterator<Item = Result<Self::Module<'a>, VmiError>> + 'a, VmiError>;
111
112    /// Returns an iterator over the processes.
113    ///
114    /// # Platform-specific
115    ///
116    /// - **Windows**: Retrieves information from the `PsActiveProcessHead` list.
117    /// - **Linux**: Retrieves information from the `tasks` list.
118    fn processes<'a>(
119        vmi: VmiState<'a, Driver, Self>,
120    ) -> Result<impl Iterator<Item = Result<Self::Process<'a>, VmiError>> + 'a, VmiError>;
121
122    /// Returns the process corresponding to the given process object.
123    fn process<'a>(
124        vmi: VmiState<'a, Driver, Self>,
125        process: ProcessObject,
126    ) -> Result<Self::Process<'a>, VmiError>;
127
128    /// Returns the currently executing process.
129    fn current_process<'a>(vmi: VmiState<'a, Driver, Self>) -> Result<Self::Process<'a>, VmiError>;
130
131    /// Returns the system process object.
132    ///
133    /// The system process is the first process created by the kernel.
134    ///
135    /// # Platform-specific
136    ///
137    /// - **Windows**: Retrieves the `PsInitialSystemProcess` global variable.
138    /// - **Linux**: Retrieves the `init_task` global variable.
139    fn system_process<'a>(vmi: VmiState<'a, Driver, Self>) -> Result<Self::Process<'a>, VmiError>;
140
141    /// Returns the thread corresponding to the given thread object.
142    fn thread<'a>(
143        vmi: VmiState<'a, Driver, Self>,
144        thread: ThreadObject,
145    ) -> Result<Self::Thread<'a>, VmiError>;
146
147    /// Returns the currently executing thread.
148    fn current_thread<'a>(vmi: VmiState<'a, Driver, Self>) -> Result<Self::Thread<'a>, VmiError>;
149
150    /// Returns the image corresponding to the given base address.
151    fn image<'a>(
152        vmi: VmiState<'a, Driver, Self>,
153        image_base: Va,
154    ) -> Result<Self::Image<'a>, VmiError>;
155
156    /// Returns the kernel module corresponding to the given base address.
157    fn module<'a>(
158        vmi: VmiState<'a, Driver, Self>,
159        module: Va,
160    ) -> Result<Self::Module<'a>, VmiError>;
161
162    /// Returns the memory region corresponding to the given address.
163    ///
164    /// # Platform-specific
165    ///
166    /// - **Windows**: The region is represented by the `_MMVAD` structure.
167    /// - **Linux**: The region is represented by the `vm_area_struct` structure.
168    fn region<'a>(
169        vmi: VmiState<'a, Driver, Self>,
170        region: Va,
171    ) -> Result<Self::Region<'a>, VmiError>;
172
173    /// Retrieves a specific syscall argument according to the system call ABI.
174    ///
175    /// This function assumes that it is called in the prologue of the system
176    /// call handler, i.e., the instruction pointer is pointing to the first
177    /// instruction of the function.
178    fn syscall_argument(vmi: VmiState<Driver, Self>, index: u64) -> Result<u64, VmiError>;
179
180    /// Retrieves a specific function argument according to the calling
181    /// convention of the operating system.
182    ///
183    /// This function assumes that it is called in the function prologue,
184    /// i.e., the instruction pointer is pointing to the first instruction of
185    /// the function.
186    ///
187    /// # Platform-specific
188    ///
189    /// - **Windows**: Assumes that the function is using the `stdcall`
190    ///   calling convention.
191    fn function_argument(vmi: VmiState<Driver, Self>, index: u64) -> Result<u64, VmiError>;
192
193    /// Retrieves the return value of a function.
194    ///
195    /// This function assumes that it is called immediately after the function
196    /// returns.
197    fn function_return_value(vmi: VmiState<Driver, Self>) -> Result<u64, VmiError>;
198
199    /// Retrieves the last error value.
200    ///
201    /// # Platform-specific
202    ///
203    /// - **Windows**: Retrieves the value of the `NtCurrentTeb()->LastErrorValue`
204    ///   field.
205    ///   - See also: [`WindowsOs::last_status()`](../../../../vmi_os_windows/struct.WindowsOs.html#method.last_status)
206    fn last_error(vmi: VmiState<Driver, Self>) -> Result<Option<u32>, VmiError>;
207}