vmi_os_windows/comps/
process_parameters.rs

1use vmi_core::{Architecture, Pa, Va, VmiDriver, VmiError, VmiState, VmiVa};
2
3use super::{macros::impl_offsets, peb::WindowsWow64Kind};
4use crate::{ArchAdapter, WindowsOs, WindowsOsExt as _};
5
6/// A Windows process parameters structure.
7///
8/// Process parameters contain command-line arguments, environment variables,
9/// and other startup information for a process. This structure supports both
10/// **32-bit and 64-bit** structures.
11pub struct WindowsProcessParameters<'a, Driver>
12where
13    Driver: VmiDriver,
14    Driver::Architecture: Architecture + ArchAdapter<Driver>,
15{
16    inner: Inner<'a, Driver>,
17}
18
19impl<Driver> VmiVa for WindowsProcessParameters<'_, Driver>
20where
21    Driver: VmiDriver,
22    Driver::Architecture: Architecture + ArchAdapter<Driver>,
23{
24    fn va(&self) -> Va {
25        match &self.inner {
26            Inner::Native(inner) => inner.va,
27            Inner::X86(inner) => inner.va,
28        }
29    }
30}
31
32impl<Driver> std::fmt::Debug for WindowsProcessParameters<'_, Driver>
33where
34    Driver: VmiDriver,
35    Driver::Architecture: Architecture + ArchAdapter<Driver>,
36{
37    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
38        let current_directory = self.current_directory();
39        let dll_path = self.dll_path();
40        let image_path_name = self.image_path_name();
41        let command_line = self.command_line();
42
43        f.debug_struct("WindowsOsProcessParameters")
44            .field("current_directory", &current_directory)
45            .field("dll_path", &dll_path)
46            .field("image_path_name", &image_path_name)
47            .field("command_line", &command_line)
48            .finish()
49    }
50}
51
52impl<'a, Driver> WindowsProcessParameters<'a, Driver>
53where
54    Driver: VmiDriver,
55    Driver::Architecture: Architecture + ArchAdapter<Driver>,
56{
57    /// Creates a new Windows process parameters structure.
58    pub(crate) fn new(
59        vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
60        va: Va,
61        root: Pa,
62        kind: WindowsWow64Kind,
63    ) -> Self {
64        let inner = match kind {
65            WindowsWow64Kind::Native => {
66                Inner::Native(WindowsProcessParametersNative::new(vmi, va, root))
67            }
68            WindowsWow64Kind::X86 => Inner::X86(WindowsProcessParameters32::new(vmi, va, root)),
69        };
70
71        Self { inner }
72    }
73
74    /// Returns the current directory.
75    ///
76    /// This method returns the full path of the current directory
77    /// for the process.
78    ///
79    /// # Implementation Details
80    ///
81    /// Corresponds to `_RTL_USER_PROCESS_PARAMETERS.CurrentDirectory`.
82    pub fn current_directory(&self) -> Result<String, VmiError> {
83        match &self.inner {
84            Inner::Native(inner) => inner.current_directory(),
85            Inner::X86(inner) => inner.current_directory(),
86        }
87    }
88
89    /// Returns the DLL search path.
90    ///
91    /// This method returns the list of directories that the system searches
92    /// when loading DLLs for the process.
93    ///
94    /// # Implementation Details
95    ///
96    /// Corresponds to `_RTL_USER_PROCESS_PARAMETERS.DllPath`.
97    pub fn dll_path(&self) -> Result<String, VmiError> {
98        match &self.inner {
99            Inner::Native(inner) => inner.dll_path(),
100            Inner::X86(inner) => inner.dll_path(),
101        }
102    }
103
104    /// Returns the full path of the executable image.
105    ///
106    /// This method retrieves the full file system path of the main executable
107    /// that was used to create the process.
108    ///
109    /// # Implementation Details
110    ///
111    /// Corresponds to `_RTL_USER_PROCESS_PARAMETERS.ImagePathName`.
112    pub fn image_path_name(&self) -> Result<String, VmiError> {
113        match &self.inner {
114            Inner::Native(inner) => inner.image_path_name(),
115            Inner::X86(inner) => inner.image_path_name(),
116        }
117    }
118
119    /// Returns the command line used to launch the process.
120    ///
121    /// This method retrieves the full command line string, including the
122    /// executable path and any arguments, used to start the process.
123    ///
124    /// # Implementation Details
125    ///
126    /// Corresponds to `_RTL_USER_PROCESS_PARAMETERS.CommandLine`.
127    pub fn command_line(&self) -> Result<String, VmiError> {
128        match &self.inner {
129            Inner::Native(inner) => inner.command_line(),
130            Inner::X86(inner) => inner.command_line(),
131        }
132    }
133}
134
135/// Inner representation of a Windows process parameters object.
136enum Inner<'a, Driver>
137where
138    Driver: VmiDriver,
139    Driver::Architecture: Architecture + ArchAdapter<Driver>,
140{
141    /// A native (non-WoW64) process.
142    Native(WindowsProcessParametersNative<'a, Driver>),
143
144    /// An x86 process running under WoW64.
145    X86(WindowsProcessParameters32<'a, Driver>),
146}
147
148struct WindowsProcessParametersNative<'a, Driver>
149where
150    Driver: VmiDriver,
151    Driver::Architecture: Architecture + ArchAdapter<Driver>,
152{
153    /// The VMI state.
154    vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
155
156    /// The virtual address of the `_RTL_USER_PROCESS_PARAMETERS` structure.
157    va: Va,
158
159    /// The translation root.
160    root: Pa,
161}
162
163impl<'a, Driver> WindowsProcessParametersNative<'a, Driver>
164where
165    Driver: VmiDriver,
166    Driver::Architecture: Architecture + ArchAdapter<Driver>,
167{
168    impl_offsets!();
169
170    fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
171        Self { vmi, va, root }
172    }
173
174    fn current_directory(&self) -> Result<String, VmiError> {
175        let offsets = self.offsets();
176        let CURDIR = &offsets._CURDIR;
177        let RTL_USER_PROCESS_PARAMETERS = &offsets._RTL_USER_PROCESS_PARAMETERS;
178
179        self.vmi.os().read_unicode_string_in((
180            self.va
181                + RTL_USER_PROCESS_PARAMETERS.CurrentDirectory.offset()
182                + CURDIR.DosPath.offset(),
183            self.root,
184        ))
185    }
186
187    fn dll_path(&self) -> Result<String, VmiError> {
188        let offsets = self.offsets();
189        let RTL_USER_PROCESS_PARAMETERS = &offsets._RTL_USER_PROCESS_PARAMETERS;
190
191        self.vmi.os().read_unicode_string_in((
192            self.va + RTL_USER_PROCESS_PARAMETERS.DllPath.offset(),
193            self.root,
194        ))
195    }
196
197    fn image_path_name(&self) -> Result<String, VmiError> {
198        let offsets = self.offsets();
199        let RTL_USER_PROCESS_PARAMETERS = &offsets._RTL_USER_PROCESS_PARAMETERS;
200
201        self.vmi.os().read_unicode_string_in((
202            self.va + RTL_USER_PROCESS_PARAMETERS.ImagePathName.offset(),
203            self.root,
204        ))
205    }
206
207    fn command_line(&self) -> Result<String, VmiError> {
208        let offsets = self.offsets();
209        let RTL_USER_PROCESS_PARAMETERS = &offsets._RTL_USER_PROCESS_PARAMETERS;
210
211        self.vmi.os().read_unicode_string_in((
212            self.va + RTL_USER_PROCESS_PARAMETERS.CommandLine.offset(),
213            self.root,
214        ))
215    }
216}
217
218struct WindowsProcessParameters32<'a, Driver>
219where
220    Driver: VmiDriver,
221    Driver::Architecture: Architecture + ArchAdapter<Driver>,
222{
223    /// The VMI state.
224    vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
225
226    /// The virtual address of the `_RTL_USER_PROCESS_PARAMETERS32` structure.
227    va: Va,
228
229    /// The translation root.
230    root: Pa,
231}
232
233impl<'a, Driver> WindowsProcessParameters32<'a, Driver>
234where
235    Driver: VmiDriver,
236    Driver::Architecture: Architecture + ArchAdapter<Driver>,
237{
238    fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
239        Self { vmi, va, root }
240    }
241
242    fn current_directory(&self) -> Result<String, VmiError> {
243        const RTL_USER_PROCESS_PARAMETERS32_CurrentDirectory_offset: u64 = 0x24;
244
245        self.vmi.os().read_unicode_string32_in((
246            self.va + RTL_USER_PROCESS_PARAMETERS32_CurrentDirectory_offset,
247            self.root,
248        ))
249    }
250
251    fn dll_path(&self) -> Result<String, VmiError> {
252        const RTL_USER_PROCESS_PARAMETERS32_DllPath_offset: u64 = 0x30;
253
254        self.vmi.os().read_unicode_string32_in((
255            self.va + RTL_USER_PROCESS_PARAMETERS32_DllPath_offset,
256            self.root,
257        ))
258    }
259
260    fn image_path_name(&self) -> Result<String, VmiError> {
261        const RTL_USER_PROCESS_PARAMETERS32_ImagePathName_offset: u64 = 0x38;
262
263        self.vmi.os().read_unicode_string32_in((
264            self.va + RTL_USER_PROCESS_PARAMETERS32_ImagePathName_offset,
265            self.root,
266        ))
267    }
268
269    fn command_line(&self) -> Result<String, VmiError> {
270        const RTL_USER_PROCESS_PARAMETERS32_CommandLine_offset: u64 = 0x40;
271
272        self.vmi.os().read_unicode_string32_in((
273            self.va + RTL_USER_PROCESS_PARAMETERS32_CommandLine_offset,
274            self.root,
275        ))
276    }
277}