1use vmi_core::{Pa, Registers as _, Va, VmiError, VmiState, VmiVa, driver::VmiRead};
2
3use super::{
4 LdrDataTableEntry, LdrDataTableEntryLayout, PebLdrData, PebLdrDataLayout, WindowsPebLdrData,
5 WindowsPebLdrDataBase, WindowsProcessParameters, WindowsProcessParametersBase,
6 WindowsWow64Kind,
7 process_parameters::{
8 CurDir, CurDirLayout, RtlUserProcessParameters, RtlUserProcessParametersLayout,
9 },
10};
11use crate::{
12 ListEntry, WindowsOs,
13 arch::{ArchAdapter, StructLayout, StructLayout32, StructLayout64},
14 iter::ListEntryLayout,
15};
16
17pub trait Peb<Layout>
19where
20 Layout: StructLayout,
21{
22 const OFFSET_LDR: u64;
24
25 const OFFSET_PROCESS_PARAMETERS: u64;
27}
28
29pub struct PebLayout;
31
32impl Peb<StructLayout32> for PebLayout {
33 const OFFSET_LDR: u64 = 0x0c;
34 const OFFSET_PROCESS_PARAMETERS: u64 = 0x10;
35}
36
37impl Peb<StructLayout64> for PebLayout {
38 const OFFSET_LDR: u64 = 0x18;
39 const OFFSET_PROCESS_PARAMETERS: u64 = 0x20;
40}
41
42pub struct WindowsPebBase<'a, Driver, Layout>
48where
49 Driver: VmiRead,
50 Driver::Architecture: ArchAdapter<Driver>,
51 Layout: StructLayout,
52 PebLayout: Peb<Layout>,
53{
54 vmi: VmiState<'a, WindowsOs<Driver>>,
56
57 va: Va,
59
60 root: Pa,
62
63 _marker: std::marker::PhantomData<Layout>,
64}
65
66impl<'a, Driver, Layout> WindowsPebBase<'a, Driver, Layout>
67where
68 Driver: VmiRead,
69 Driver::Architecture: ArchAdapter<Driver>,
70 Layout: StructLayout,
71 PebLayout: Peb<Layout>,
72{
73 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
75 Self {
76 vmi,
77 va,
78 root,
79 _marker: std::marker::PhantomData,
80 }
81 }
82
83 pub fn ldr(&self) -> Result<WindowsPebLdrDataBase<'a, Driver, Layout>, VmiError>
85 where
86 ListEntryLayout: ListEntry<Layout>,
87 PebLdrDataLayout: PebLdrData<Layout>,
88 LdrDataTableEntryLayout: LdrDataTableEntry<Layout>,
89 {
90 let va = Layout::read_va(self.vmi, (self.va + PebLayout::OFFSET_LDR, self.root))?;
91 Ok(WindowsPebLdrDataBase::new(self.vmi, va, self.root))
92 }
93
94 pub fn process_parameters(
96 &self,
97 ) -> Result<WindowsProcessParametersBase<'a, Driver, Layout>, VmiError>
98 where
99 RtlUserProcessParametersLayout: RtlUserProcessParameters<Layout>,
100 CurDirLayout: CurDir<Layout>,
101 {
102 let va = Layout::read_va(
103 self.vmi,
104 (self.va + PebLayout::OFFSET_PROCESS_PARAMETERS, self.root),
105 )?;
106 Ok(WindowsProcessParametersBase::new(self.vmi, va, self.root))
107 }
108}
109
110enum WindowsPebWrapper<'a, Driver>
111where
112 Driver: VmiRead,
113 Driver::Architecture: ArchAdapter<Driver>,
114{
115 W32(WindowsPebBase<'a, Driver, StructLayout32>),
116 W64(WindowsPebBase<'a, Driver, StructLayout64>),
117}
118
119impl<'a, Driver> WindowsPebWrapper<'a, Driver>
120where
121 Driver: VmiRead,
122 Driver::Architecture: ArchAdapter<Driver>,
123{
124 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
125 Self::W32(WindowsPebBase::new(vmi, va, root))
126 }
127
128 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
129 Self::W64(WindowsPebBase::new(vmi, va, root))
130 }
131
132 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
133 match vmi.registers().address_width() {
134 4 => Self::w32(vmi, va, root),
135 8 => Self::w64(vmi, va, root),
136 _ => panic!("Unsupported address width"),
137 }
138 }
139
140 fn ldr(&self) -> Result<WindowsPebLdrData<'a, Driver>, VmiError> {
141 match self {
142 Self::W32(inner) => Ok(WindowsPebLdrData::from(inner.ldr()?)),
143 Self::W64(inner) => Ok(WindowsPebLdrData::from(inner.ldr()?)),
144 }
145 }
146
147 fn process_parameters(&self) -> Result<WindowsProcessParameters<'a, Driver>, VmiError> {
148 match self {
149 Self::W32(inner) => Ok(WindowsProcessParameters::from(inner.process_parameters()?)),
150 Self::W64(inner) => Ok(WindowsProcessParameters::from(inner.process_parameters()?)),
151 }
152 }
153}
154
155pub struct WindowsPeb<'a, Driver>
164where
165 Driver: VmiRead,
166 Driver::Architecture: ArchAdapter<Driver>,
167{
168 inner: WindowsPebWrapper<'a, Driver>,
169}
170
171impl<Driver> VmiVa for WindowsPeb<'_, Driver>
172where
173 Driver: VmiRead,
174 Driver::Architecture: ArchAdapter<Driver>,
175{
176 fn va(&self) -> Va {
177 match &self.inner {
178 WindowsPebWrapper::W32(inner) => inner.va,
179 WindowsPebWrapper::W64(inner) => inner.va,
180 }
181 }
182}
183
184impl<'a, Driver> From<WindowsPebBase<'a, Driver, StructLayout32>> for WindowsPeb<'a, Driver>
185where
186 Driver: VmiRead,
187 Driver::Architecture: ArchAdapter<Driver>,
188{
189 fn from(value: WindowsPebBase<'a, Driver, StructLayout32>) -> Self {
190 Self {
191 inner: WindowsPebWrapper::W32(value),
192 }
193 }
194}
195
196impl<'a, Driver> From<WindowsPebBase<'a, Driver, StructLayout64>> for WindowsPeb<'a, Driver>
197where
198 Driver: VmiRead,
199 Driver::Architecture: ArchAdapter<Driver>,
200{
201 fn from(value: WindowsPebBase<'a, Driver, StructLayout64>) -> Self {
202 Self {
203 inner: WindowsPebWrapper::W64(value),
204 }
205 }
206}
207
208impl<Driver> std::fmt::Debug for WindowsPeb<'_, Driver>
209where
210 Driver: VmiRead,
211 Driver::Architecture: ArchAdapter<Driver>,
212{
213 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
214 let process_parameters = self.process_parameters();
215
216 f.debug_struct("WindowsPeb")
217 .field("process_parameters", &process_parameters)
218 .finish()
219 }
220}
221
222impl<'a, Driver> WindowsPeb<'a, Driver>
223where
224 Driver: VmiRead,
225 Driver::Architecture: ArchAdapter<Driver>,
226{
227 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
229 Self::with_kind(vmi, va, vmi.translation_root(va), WindowsWow64Kind::Native)
230 }
231
232 pub fn with_kind(
235 vmi: VmiState<'a, WindowsOs<Driver>>,
236 va: Va,
237 root: Pa,
238 kind: WindowsWow64Kind,
239 ) -> Self {
240 let inner = match kind {
241 WindowsWow64Kind::Native => WindowsPebWrapper::native(vmi, va, root),
242 WindowsWow64Kind::X86 => WindowsPebWrapper::w32(vmi, va, root),
243 };
244
245 Self { inner }
246 }
247
248 pub fn ldr(&self) -> Result<WindowsPebLdrData<'a, Driver>, VmiError> {
257 self.inner.ldr()
258 }
259
260 pub fn process_parameters(&self) -> Result<WindowsProcessParameters<'a, Driver>, VmiError> {
266 self.inner.process_parameters()
267 }
268
269 pub fn current_directory(&self) -> Result<String, VmiError> {
275 self.process_parameters()?.current_directory()
276 }
277
278 pub fn dll_path(&self) -> Result<String, VmiError> {
284 self.process_parameters()?.dll_path()
285 }
286
287 pub fn image_path_name(&self) -> Result<String, VmiError> {
293 self.process_parameters()?.image_path_name()
294 }
295
296 pub fn command_line(&self) -> Result<String, VmiError> {
302 self.process_parameters()?.command_line()
303 }
304}