1use vmi_core::{Pa, Registers as _, Va, VmiError, VmiState, VmiVa, driver::VmiRead};
2
3use super::WindowsWow64Kind;
4use crate::{
5 WindowsOs,
6 arch::{ArchAdapter, StructLayout, StructLayout32, StructLayout64},
7};
8
9pub trait RtlUserProcessParameters<Layout>
11where
12 Layout: StructLayout,
13{
14 const OFFSET_CURRENT_DIRECTORY: u64;
16
17 const OFFSET_DLL_PATH: u64;
19
20 const OFFSET_IMAGE_PATH_NAME: u64;
22
23 const OFFSET_COMMAND_LINE: u64;
25}
26
27pub struct RtlUserProcessParametersLayout;
29
30impl RtlUserProcessParameters<StructLayout32> for RtlUserProcessParametersLayout {
31 const OFFSET_CURRENT_DIRECTORY: u64 = 0x24;
32 const OFFSET_DLL_PATH: u64 = 0x30;
33 const OFFSET_IMAGE_PATH_NAME: u64 = 0x38;
34 const OFFSET_COMMAND_LINE: u64 = 0x40;
35}
36
37impl RtlUserProcessParameters<StructLayout64> for RtlUserProcessParametersLayout {
38 const OFFSET_CURRENT_DIRECTORY: u64 = 0x38;
39 const OFFSET_DLL_PATH: u64 = 0x50;
40 const OFFSET_IMAGE_PATH_NAME: u64 = 0x60;
41 const OFFSET_COMMAND_LINE: u64 = 0x70;
42}
43
44pub trait CurDir<Layout>
46where
47 Layout: StructLayout,
48{
49 const OFFSET_DOS_PATH: u64;
51}
52
53pub struct CurDirLayout;
55
56impl CurDir<StructLayout32> for CurDirLayout {
57 const OFFSET_DOS_PATH: u64 = 0x00;
58}
59
60impl CurDir<StructLayout64> for CurDirLayout {
61 const OFFSET_DOS_PATH: u64 = 0x00;
62}
63
64pub struct WindowsProcessParametersBase<'a, Driver, Layout>
70where
71 Driver: VmiRead,
72 Driver::Architecture: ArchAdapter<Driver>,
73 Layout: StructLayout,
74 RtlUserProcessParametersLayout: RtlUserProcessParameters<Layout>,
75{
76 vmi: VmiState<'a, WindowsOs<Driver>>,
78
79 va: Va,
81
82 root: Pa,
84
85 _marker: std::marker::PhantomData<Layout>,
86}
87
88impl<'a, Driver, Layout> WindowsProcessParametersBase<'a, Driver, Layout>
89where
90 Driver: VmiRead,
91 Driver::Architecture: ArchAdapter<Driver>,
92 Layout: StructLayout,
93 RtlUserProcessParametersLayout: RtlUserProcessParameters<Layout>,
94 CurDirLayout: CurDir<Layout>,
95{
96 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
98 Self {
99 vmi,
100 va,
101 root,
102 _marker: std::marker::PhantomData,
103 }
104 }
105
106 pub fn current_directory(&self) -> Result<String, VmiError> {
112 Layout::read_unicode_string(
113 self.vmi,
114 (
115 self.va
116 + RtlUserProcessParametersLayout::OFFSET_CURRENT_DIRECTORY
117 + CurDirLayout::OFFSET_DOS_PATH,
118 self.root,
119 ),
120 )
121 }
122
123 pub fn dll_path(&self) -> Result<String, VmiError> {
129 Layout::read_unicode_string(
130 self.vmi,
131 (
132 self.va + RtlUserProcessParametersLayout::OFFSET_DLL_PATH,
133 self.root,
134 ),
135 )
136 }
137
138 pub fn image_path_name(&self) -> Result<String, VmiError> {
144 Layout::read_unicode_string(
145 self.vmi,
146 (
147 self.va + RtlUserProcessParametersLayout::OFFSET_IMAGE_PATH_NAME,
148 self.root,
149 ),
150 )
151 }
152
153 pub fn command_line(&self) -> Result<String, VmiError> {
159 Layout::read_unicode_string(
160 self.vmi,
161 (
162 self.va + RtlUserProcessParametersLayout::OFFSET_COMMAND_LINE,
163 self.root,
164 ),
165 )
166 }
167}
168
169enum WindowsProcessParametersWrapper<'a, Driver>
170where
171 Driver: VmiRead,
172 Driver::Architecture: ArchAdapter<Driver>,
173{
174 W32(WindowsProcessParametersBase<'a, Driver, StructLayout32>),
175 W64(WindowsProcessParametersBase<'a, Driver, StructLayout64>),
176}
177
178impl<'a, Driver> WindowsProcessParametersWrapper<'a, Driver>
179where
180 Driver: VmiRead,
181 Driver::Architecture: ArchAdapter<Driver>,
182{
183 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
184 Self::W32(WindowsProcessParametersBase::new(vmi, va, root))
185 }
186
187 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
188 Self::W64(WindowsProcessParametersBase::new(vmi, va, root))
189 }
190
191 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
192 match vmi.registers().address_width() {
193 4 => Self::w32(vmi, va, root),
194 8 => Self::w64(vmi, va, root),
195 _ => panic!("Unsupported address width"),
196 }
197 }
198
199 fn current_directory(&self) -> Result<String, VmiError> {
200 match self {
201 Self::W32(inner) => inner.current_directory(),
202 Self::W64(inner) => inner.current_directory(),
203 }
204 }
205
206 fn dll_path(&self) -> Result<String, VmiError> {
207 match self {
208 Self::W32(inner) => inner.dll_path(),
209 Self::W64(inner) => inner.dll_path(),
210 }
211 }
212
213 fn image_path_name(&self) -> Result<String, VmiError> {
214 match self {
215 Self::W32(inner) => inner.image_path_name(),
216 Self::W64(inner) => inner.image_path_name(),
217 }
218 }
219
220 fn command_line(&self) -> Result<String, VmiError> {
221 match self {
222 Self::W32(inner) => inner.command_line(),
223 Self::W64(inner) => inner.command_line(),
224 }
225 }
226}
227
228pub struct WindowsProcessParameters<'a, Driver>
237where
238 Driver: VmiRead,
239 Driver::Architecture: ArchAdapter<Driver>,
240{
241 inner: WindowsProcessParametersWrapper<'a, Driver>,
242}
243
244impl<'a, Driver> From<WindowsProcessParametersBase<'a, Driver, StructLayout32>>
245 for WindowsProcessParameters<'a, Driver>
246where
247 Driver: VmiRead,
248 Driver::Architecture: ArchAdapter<Driver>,
249{
250 fn from(value: WindowsProcessParametersBase<'a, Driver, StructLayout32>) -> Self {
251 Self {
252 inner: WindowsProcessParametersWrapper::W32(value),
253 }
254 }
255}
256
257impl<'a, Driver> From<WindowsProcessParametersBase<'a, Driver, StructLayout64>>
258 for WindowsProcessParameters<'a, Driver>
259where
260 Driver: VmiRead,
261 Driver::Architecture: ArchAdapter<Driver>,
262{
263 fn from(value: WindowsProcessParametersBase<'a, Driver, StructLayout64>) -> Self {
264 Self {
265 inner: WindowsProcessParametersWrapper::W64(value),
266 }
267 }
268}
269
270impl<Driver> VmiVa for WindowsProcessParameters<'_, Driver>
271where
272 Driver: VmiRead,
273 Driver::Architecture: ArchAdapter<Driver>,
274{
275 fn va(&self) -> Va {
276 match &self.inner {
277 WindowsProcessParametersWrapper::W32(inner) => inner.va,
278 WindowsProcessParametersWrapper::W64(inner) => inner.va,
279 }
280 }
281}
282
283impl<Driver> std::fmt::Debug for WindowsProcessParameters<'_, Driver>
284where
285 Driver: VmiRead,
286 Driver::Architecture: ArchAdapter<Driver>,
287{
288 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
289 let current_directory = self.current_directory();
290 let dll_path = self.dll_path();
291 let image_path_name = self.image_path_name();
292 let command_line = self.command_line();
293
294 f.debug_struct("WindowsProcessParameters")
295 .field("current_directory", ¤t_directory)
296 .field("dll_path", &dll_path)
297 .field("image_path_name", &image_path_name)
298 .field("command_line", &command_line)
299 .finish()
300 }
301}
302
303impl<'a, Driver> WindowsProcessParameters<'a, Driver>
304where
305 Driver: VmiRead,
306 Driver::Architecture: ArchAdapter<Driver>,
307{
308 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
310 Self::with_kind(vmi, va, vmi.translation_root(va), WindowsWow64Kind::Native)
311 }
312
313 pub fn with_kind(
316 vmi: VmiState<'a, WindowsOs<Driver>>,
317 va: Va,
318 root: Pa,
319 kind: WindowsWow64Kind,
320 ) -> Self {
321 let inner = match kind {
322 WindowsWow64Kind::Native => WindowsProcessParametersWrapper::native(vmi, va, root),
323 WindowsWow64Kind::X86 => WindowsProcessParametersWrapper::w32(vmi, va, root),
324 };
325
326 Self { inner }
327 }
328
329 pub fn current_directory(&self) -> Result<String, VmiError> {
335 self.inner.current_directory()
336 }
337
338 pub fn dll_path(&self) -> Result<String, VmiError> {
344 self.inner.dll_path()
345 }
346
347 pub fn image_path_name(&self) -> Result<String, VmiError> {
353 self.inner.image_path_name()
354 }
355
356 pub fn command_line(&self) -> Result<String, VmiError> {
362 self.inner.command_line()
363 }
364}