1use vmi_core::{Pa, Registers as _, Va, VmiError, VmiState, VmiVa, driver::VmiRead};
2
3use super::{WindowsUserModule, WindowsWow64Kind};
4use crate::{
5 ArchAdapter, ListEntry, ListEntryIterator, ListEntryIteratorBase, WindowsOs,
6 arch::{StructLayout, StructLayout32, StructLayout64},
7 iter::ListEntryLayout,
8};
9
10pub trait PebLdrData<Layout>
12where
13 Layout: StructLayout,
14{
15 const OFFSET_IN_LOAD_ORDER_MODULE_LIST: u64;
17
18 const OFFSET_IN_MEMORY_ORDER_MODULE_LIST: u64;
20
21 const OFFSET_IN_INITIALIZATION_ORDER_MODULE_LIST: u64;
23}
24
25pub struct PebLdrDataLayout;
27
28impl PebLdrData<StructLayout32> for PebLdrDataLayout {
29 const OFFSET_IN_LOAD_ORDER_MODULE_LIST: u64 = 0x0c;
30 const OFFSET_IN_MEMORY_ORDER_MODULE_LIST: u64 = 0x14;
31 const OFFSET_IN_INITIALIZATION_ORDER_MODULE_LIST: u64 = 0x1c;
32}
33
34impl PebLdrData<StructLayout64> for PebLdrDataLayout {
35 const OFFSET_IN_LOAD_ORDER_MODULE_LIST: u64 = 0x10;
36 const OFFSET_IN_MEMORY_ORDER_MODULE_LIST: u64 = 0x20;
37 const OFFSET_IN_INITIALIZATION_ORDER_MODULE_LIST: u64 = 0x30;
38}
39
40pub trait LdrDataTableEntry<Layout>
42where
43 Layout: StructLayout,
44{
45 const OFFSET_IN_LOAD_ORDER_LINKS: u64;
47
48 const OFFSET_IN_MEMORY_ORDER_LINKS: u64;
50
51 const OFFSET_IN_INITIALIZATION_ORDER_LINKS: u64;
53}
54
55pub struct LdrDataTableEntryLayout;
57
58impl LdrDataTableEntry<StructLayout32> for LdrDataTableEntryLayout {
59 const OFFSET_IN_LOAD_ORDER_LINKS: u64 = 0x00;
60 const OFFSET_IN_MEMORY_ORDER_LINKS: u64 = 0x08;
61 const OFFSET_IN_INITIALIZATION_ORDER_LINKS: u64 = 0x10;
62}
63
64impl LdrDataTableEntry<StructLayout64> for LdrDataTableEntryLayout {
65 const OFFSET_IN_LOAD_ORDER_LINKS: u64 = 0x00;
66 const OFFSET_IN_MEMORY_ORDER_LINKS: u64 = 0x10;
67 const OFFSET_IN_INITIALIZATION_ORDER_LINKS: u64 = 0x20;
68}
69
70pub struct WindowsPebLdrDataBase<'a, Driver, Layout>
76where
77 Driver: VmiRead,
78 Driver::Architecture: ArchAdapter<Driver>,
79 Layout: StructLayout,
80 PebLdrDataLayout: PebLdrData<Layout>,
81{
82 vmi: VmiState<'a, WindowsOs<Driver>>,
84
85 va: Va,
87
88 root: Pa,
90
91 _marker: std::marker::PhantomData<Layout>,
92}
93
94impl<'a, Driver, Layout> WindowsPebLdrDataBase<'a, Driver, Layout>
95where
96 Driver: VmiRead,
97 Driver::Architecture: ArchAdapter<Driver>,
98 Layout: StructLayout,
99 ListEntryLayout: ListEntry<Layout>,
100 PebLdrDataLayout: PebLdrData<Layout>,
101 LdrDataTableEntryLayout: LdrDataTableEntry<Layout>,
102{
103 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
105 Self {
106 vmi,
107 va,
108 root,
109 _marker: std::marker::PhantomData,
110 }
111 }
112
113 pub fn in_load_order_modules(
119 &self,
120 ) -> Result<
121 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver, Layout>,
122 VmiError,
123 > {
124 let vmi = self.vmi;
125 let root = self.root;
126 Ok(self
127 .in_load_order_modules_inner()
128 .map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
129 }
130
131 pub fn in_memory_order_modules(
137 &self,
138 ) -> Result<
139 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver, Layout>,
140 VmiError,
141 > {
142 let vmi = self.vmi;
143 let root = self.root;
144 Ok(self
145 .in_memory_order_modules_inner()
146 .map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
147 }
148
149 pub fn in_initialization_order_modules(
155 &self,
156 ) -> Result<
157 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver, Layout>,
158 VmiError,
159 > {
160 let vmi = self.vmi;
161 let root = self.root;
162 Ok(self
163 .in_initialization_order_modules_inner()
164 .map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
165 }
166
167 fn in_load_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
168 self.make_iterator(
169 self.va + PebLdrDataLayout::OFFSET_IN_LOAD_ORDER_MODULE_LIST,
170 LdrDataTableEntryLayout::OFFSET_IN_LOAD_ORDER_LINKS,
171 )
172 }
173
174 fn in_memory_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
175 self.make_iterator(
176 self.va + PebLdrDataLayout::OFFSET_IN_MEMORY_ORDER_MODULE_LIST,
177 LdrDataTableEntryLayout::OFFSET_IN_MEMORY_ORDER_LINKS,
178 )
179 }
180
181 fn in_initialization_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
182 self.make_iterator(
183 self.va + PebLdrDataLayout::OFFSET_IN_INITIALIZATION_ORDER_MODULE_LIST,
184 LdrDataTableEntryLayout::OFFSET_IN_INITIALIZATION_ORDER_LINKS,
185 )
186 }
187
188 fn make_iterator(
189 &self,
190 list_head: Va,
191 link_offset: u64,
192 ) -> ListEntryIteratorBase<'a, Driver, Layout> {
193 ListEntryIteratorBase::new(self.vmi, list_head, link_offset, self.root)
194 }
195}
196
197enum WindowsPebLdrDataWrapper<'a, Driver>
198where
199 Driver: VmiRead,
200 Driver::Architecture: ArchAdapter<Driver>,
201{
202 W32(WindowsPebLdrDataBase<'a, Driver, StructLayout32>),
203 W64(WindowsPebLdrDataBase<'a, Driver, StructLayout64>),
204}
205
206impl<'a, Driver> WindowsPebLdrDataWrapper<'a, Driver>
207where
208 Driver: VmiRead,
209 Driver::Architecture: ArchAdapter<Driver>,
210{
211 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
212 Self::W32(WindowsPebLdrDataBase::new(vmi, va, root))
213 }
214
215 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
216 Self::W64(WindowsPebLdrDataBase::new(vmi, va, root))
217 }
218
219 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
220 match vmi.registers().address_width() {
221 4 => Self::w32(vmi, va, root),
222 8 => Self::w64(vmi, va, root),
223 _ => panic!("Unsupported address width"),
224 }
225 }
226
227 fn in_load_order_modules(
228 &self,
229 ) -> Result<
230 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
231 VmiError,
232 > {
233 let (iter, vmi, root) = match self {
234 Self::W32(inner) => (
235 ListEntryIterator::from(inner.in_load_order_modules_inner()),
236 inner.vmi,
237 inner.root,
238 ),
239 Self::W64(inner) => (
240 ListEntryIterator::from(inner.in_load_order_modules_inner()),
241 inner.vmi,
242 inner.root,
243 ),
244 };
245
246 Ok(iter.map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
247 }
248
249 fn in_memory_order_modules(
250 &self,
251 ) -> Result<
252 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
253 VmiError,
254 > {
255 let (iter, vmi, root) = match self {
256 Self::W32(inner) => (
257 ListEntryIterator::from(inner.in_memory_order_modules_inner()),
258 inner.vmi,
259 inner.root,
260 ),
261 Self::W64(inner) => (
262 ListEntryIterator::from(inner.in_memory_order_modules_inner()),
263 inner.vmi,
264 inner.root,
265 ),
266 };
267
268 Ok(iter.map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
269 }
270
271 fn in_initialization_order_modules(
272 &self,
273 ) -> Result<
274 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
275 VmiError,
276 > {
277 let (iter, vmi, root) = match self {
278 Self::W32(inner) => (
279 ListEntryIterator::from(inner.in_initialization_order_modules_inner()),
280 inner.vmi,
281 inner.root,
282 ),
283 Self::W64(inner) => (
284 ListEntryIterator::from(inner.in_initialization_order_modules_inner()),
285 inner.vmi,
286 inner.root,
287 ),
288 };
289
290 Ok(iter.map(move |result| result.map(|va| WindowsUserModule::new(vmi, va, root))))
291 }
292}
293
294pub struct WindowsPebLdrData<'a, Driver>
300where
301 Driver: VmiRead,
302 Driver::Architecture: ArchAdapter<Driver>,
303{
304 inner: WindowsPebLdrDataWrapper<'a, Driver>,
305}
306
307impl<'a, Driver> From<WindowsPebLdrDataBase<'a, Driver, StructLayout32>>
308 for WindowsPebLdrData<'a, Driver>
309where
310 Driver: VmiRead,
311 Driver::Architecture: ArchAdapter<Driver>,
312{
313 fn from(value: WindowsPebLdrDataBase<'a, Driver, StructLayout32>) -> Self {
314 Self {
315 inner: WindowsPebLdrDataWrapper::W32(value),
316 }
317 }
318}
319
320impl<'a, Driver> From<WindowsPebLdrDataBase<'a, Driver, StructLayout64>>
321 for WindowsPebLdrData<'a, Driver>
322where
323 Driver: VmiRead,
324 Driver::Architecture: ArchAdapter<Driver>,
325{
326 fn from(value: WindowsPebLdrDataBase<'a, Driver, StructLayout64>) -> Self {
327 Self {
328 inner: WindowsPebLdrDataWrapper::W64(value),
329 }
330 }
331}
332
333impl<Driver> VmiVa for WindowsPebLdrData<'_, Driver>
334where
335 Driver: VmiRead,
336 Driver::Architecture: ArchAdapter<Driver>,
337{
338 fn va(&self) -> Va {
339 match &self.inner {
340 WindowsPebLdrDataWrapper::W32(inner) => inner.va,
341 WindowsPebLdrDataWrapper::W64(inner) => inner.va,
342 }
343 }
344}
345
346impl<'a, Driver> WindowsPebLdrData<'a, Driver>
347where
348 Driver: VmiRead,
349 Driver::Architecture: ArchAdapter<Driver>,
350{
351 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
353 Self::with_kind(vmi, va, vmi.translation_root(va), WindowsWow64Kind::Native)
354 }
355
356 pub fn with_kind(
359 vmi: VmiState<'a, WindowsOs<Driver>>,
360 va: Va,
361 root: Pa,
362 kind: WindowsWow64Kind,
363 ) -> Self {
364 let inner = match kind {
365 WindowsWow64Kind::Native => WindowsPebLdrDataWrapper::native(vmi, va, root),
366 WindowsWow64Kind::X86 => WindowsPebLdrDataWrapper::w32(vmi, va, root),
367 };
368
369 Self { inner }
370 }
371
372 pub fn in_load_order_modules(
378 &self,
379 ) -> Result<
380 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
381 VmiError,
382 > {
383 self.inner.in_load_order_modules()
384 }
385
386 pub fn in_memory_order_modules(
392 &self,
393 ) -> Result<
394 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
395 VmiError,
396 > {
397 self.inner.in_memory_order_modules()
398 }
399
400 pub fn in_initialization_order_modules(
406 &self,
407 ) -> Result<
408 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
409 VmiError,
410 > {
411 self.inner.in_initialization_order_modules()
412 }
413}