1use vmi_core::{Pa, Registers as _, Va, VmiError, VmiState, VmiVa, driver::VmiRead};
2
3use super::{WindowsUserModule, WindowsUserModuleBase, 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 const OFFSET_DLL_BASE: u64;
56
57 const OFFSET_ENTRY_POINT: u64;
59
60 const OFFSET_SIZE_OF_IMAGE: u64;
62
63 const OFFSET_FULL_DLL_NAME: u64;
65
66 const OFFSET_BASE_DLL_NAME: u64;
68
69 const OFFSET_TIME_DATE_STAMP: u64;
71}
72
73pub struct LdrDataTableEntryLayout;
75
76impl LdrDataTableEntry<StructLayout32> for LdrDataTableEntryLayout {
77 const OFFSET_IN_LOAD_ORDER_LINKS: u64 = 0x00;
78 const OFFSET_IN_MEMORY_ORDER_LINKS: u64 = 0x08;
79 const OFFSET_IN_INITIALIZATION_ORDER_LINKS: u64 = 0x10;
80 const OFFSET_DLL_BASE: u64 = 0x18;
81 const OFFSET_ENTRY_POINT: u64 = 0x1c;
82 const OFFSET_SIZE_OF_IMAGE: u64 = 0x20;
83 const OFFSET_FULL_DLL_NAME: u64 = 0x24;
84 const OFFSET_BASE_DLL_NAME: u64 = 0x2c;
85 const OFFSET_TIME_DATE_STAMP: u64 = 0x44;
86}
87
88impl LdrDataTableEntry<StructLayout64> for LdrDataTableEntryLayout {
89 const OFFSET_IN_LOAD_ORDER_LINKS: u64 = 0x00;
90 const OFFSET_IN_MEMORY_ORDER_LINKS: u64 = 0x10;
91 const OFFSET_IN_INITIALIZATION_ORDER_LINKS: u64 = 0x20;
92 const OFFSET_DLL_BASE: u64 = 0x30;
93 const OFFSET_ENTRY_POINT: u64 = 0x38;
94 const OFFSET_SIZE_OF_IMAGE: u64 = 0x40;
95 const OFFSET_FULL_DLL_NAME: u64 = 0x48;
96 const OFFSET_BASE_DLL_NAME: u64 = 0x58;
97 const OFFSET_TIME_DATE_STAMP: u64 = 0x80;
98}
99
100pub struct WindowsPebLdrDataBase<'a, Driver, Layout>
106where
107 Driver: VmiRead,
108 Driver::Architecture: ArchAdapter<Driver>,
109 Layout: StructLayout,
110 PebLdrDataLayout: PebLdrData<Layout>,
111{
112 vmi: VmiState<'a, WindowsOs<Driver>>,
114
115 va: Va,
117
118 root: Pa,
120
121 _marker: std::marker::PhantomData<Layout>,
122}
123
124impl<'a, Driver, Layout> WindowsPebLdrDataBase<'a, Driver, Layout>
125where
126 Driver: VmiRead,
127 Driver::Architecture: ArchAdapter<Driver>,
128 Layout: StructLayout,
129 ListEntryLayout: ListEntry<Layout>,
130 PebLdrDataLayout: PebLdrData<Layout>,
131 LdrDataTableEntryLayout: LdrDataTableEntry<Layout>,
132{
133 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
135 Self {
136 vmi,
137 va,
138 root,
139 _marker: std::marker::PhantomData,
140 }
141 }
142
143 pub fn in_load_order_modules(
149 &self,
150 ) -> Result<
151 impl Iterator<Item = Result<WindowsUserModuleBase<'a, Driver, Layout>, VmiError>>
152 + use<'a, Driver, Layout>,
153 VmiError,
154 > {
155 let vmi = self.vmi;
156 let root = self.root;
157 Ok(self
158 .in_load_order_modules_inner()
159 .map(move |result| result.map(|va| WindowsUserModuleBase::new(vmi, va, root))))
160 }
161
162 pub fn in_memory_order_modules(
168 &self,
169 ) -> Result<
170 impl Iterator<Item = Result<WindowsUserModuleBase<'a, Driver, Layout>, VmiError>>
171 + use<'a, Driver, Layout>,
172 VmiError,
173 > {
174 let vmi = self.vmi;
175 let root = self.root;
176 Ok(self
177 .in_memory_order_modules_inner()
178 .map(move |result| result.map(|va| WindowsUserModuleBase::new(vmi, va, root))))
179 }
180
181 pub fn in_initialization_order_modules(
187 &self,
188 ) -> Result<
189 impl Iterator<Item = Result<WindowsUserModuleBase<'a, Driver, Layout>, VmiError>>
190 + use<'a, Driver, Layout>,
191 VmiError,
192 > {
193 let vmi = self.vmi;
194 let root = self.root;
195 Ok(self
196 .in_initialization_order_modules_inner()
197 .map(move |result| result.map(|va| WindowsUserModuleBase::new(vmi, va, root))))
198 }
199
200 fn in_load_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
201 self.make_iterator(
202 self.va + PebLdrDataLayout::OFFSET_IN_LOAD_ORDER_MODULE_LIST,
203 LdrDataTableEntryLayout::OFFSET_IN_LOAD_ORDER_LINKS,
204 )
205 }
206
207 fn in_memory_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
208 self.make_iterator(
209 self.va + PebLdrDataLayout::OFFSET_IN_MEMORY_ORDER_MODULE_LIST,
210 LdrDataTableEntryLayout::OFFSET_IN_MEMORY_ORDER_LINKS,
211 )
212 }
213
214 fn in_initialization_order_modules_inner(&self) -> ListEntryIteratorBase<'a, Driver, Layout> {
215 self.make_iterator(
216 self.va + PebLdrDataLayout::OFFSET_IN_INITIALIZATION_ORDER_MODULE_LIST,
217 LdrDataTableEntryLayout::OFFSET_IN_INITIALIZATION_ORDER_LINKS,
218 )
219 }
220
221 fn make_iterator(
222 &self,
223 list_head: Va,
224 link_offset: u64,
225 ) -> ListEntryIteratorBase<'a, Driver, Layout> {
226 ListEntryIteratorBase::new(self.vmi, list_head, link_offset, self.root)
227 }
228}
229
230enum WindowsPebLdrDataWrapper<'a, Driver>
231where
232 Driver: VmiRead,
233 Driver::Architecture: ArchAdapter<Driver>,
234{
235 W32(WindowsPebLdrDataBase<'a, Driver, StructLayout32>),
236 W64(WindowsPebLdrDataBase<'a, Driver, StructLayout64>),
237}
238
239impl<'a, Driver> WindowsPebLdrDataWrapper<'a, Driver>
240where
241 Driver: VmiRead,
242 Driver::Architecture: ArchAdapter<Driver>,
243{
244 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
245 Self::W32(WindowsPebLdrDataBase::new(vmi, va, root))
246 }
247
248 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
249 Self::W64(WindowsPebLdrDataBase::new(vmi, va, root))
250 }
251
252 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
253 match vmi.registers().address_width() {
254 4 => Self::w32(vmi, va, root),
255 8 => Self::w64(vmi, va, root),
256 _ => panic!("Unsupported address width"),
257 }
258 }
259
260 fn in_load_order_modules(
261 &self,
262 ) -> Result<
263 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
264 VmiError,
265 > {
266 let (iter, vmi, root, kind) = match self {
267 Self::W32(inner) => (
268 ListEntryIterator::from(inner.in_load_order_modules_inner()),
269 inner.vmi,
270 inner.root,
271 WindowsWow64Kind::X86,
272 ),
273 Self::W64(inner) => (
274 ListEntryIterator::from(inner.in_load_order_modules_inner()),
275 inner.vmi,
276 inner.root,
277 WindowsWow64Kind::Native,
278 ),
279 };
280
281 Ok(iter
282 .map(move |result| result.map(|va| WindowsUserModule::with_kind(vmi, va, root, kind))))
283 }
284
285 fn in_memory_order_modules(
286 &self,
287 ) -> Result<
288 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
289 VmiError,
290 > {
291 let (iter, vmi, root, kind) = match self {
292 Self::W32(inner) => (
293 ListEntryIterator::from(inner.in_memory_order_modules_inner()),
294 inner.vmi,
295 inner.root,
296 WindowsWow64Kind::X86,
297 ),
298 Self::W64(inner) => (
299 ListEntryIterator::from(inner.in_memory_order_modules_inner()),
300 inner.vmi,
301 inner.root,
302 WindowsWow64Kind::Native,
303 ),
304 };
305
306 Ok(iter
307 .map(move |result| result.map(|va| WindowsUserModule::with_kind(vmi, va, root, kind))))
308 }
309
310 fn in_initialization_order_modules(
311 &self,
312 ) -> Result<
313 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
314 VmiError,
315 > {
316 let (iter, vmi, root, kind) = match self {
317 Self::W32(inner) => (
318 ListEntryIterator::from(inner.in_initialization_order_modules_inner()),
319 inner.vmi,
320 inner.root,
321 WindowsWow64Kind::X86,
322 ),
323 Self::W64(inner) => (
324 ListEntryIterator::from(inner.in_initialization_order_modules_inner()),
325 inner.vmi,
326 inner.root,
327 WindowsWow64Kind::Native,
328 ),
329 };
330
331 Ok(iter
332 .map(move |result| result.map(|va| WindowsUserModule::with_kind(vmi, va, root, kind))))
333 }
334}
335
336pub struct WindowsPebLdrData<'a, Driver>
342where
343 Driver: VmiRead,
344 Driver::Architecture: ArchAdapter<Driver>,
345{
346 inner: WindowsPebLdrDataWrapper<'a, Driver>,
347}
348
349impl<'a, Driver> From<WindowsPebLdrDataBase<'a, Driver, StructLayout32>>
350 for WindowsPebLdrData<'a, Driver>
351where
352 Driver: VmiRead,
353 Driver::Architecture: ArchAdapter<Driver>,
354{
355 fn from(value: WindowsPebLdrDataBase<'a, Driver, StructLayout32>) -> Self {
356 Self {
357 inner: WindowsPebLdrDataWrapper::W32(value),
358 }
359 }
360}
361
362impl<'a, Driver> From<WindowsPebLdrDataBase<'a, Driver, StructLayout64>>
363 for WindowsPebLdrData<'a, Driver>
364where
365 Driver: VmiRead,
366 Driver::Architecture: ArchAdapter<Driver>,
367{
368 fn from(value: WindowsPebLdrDataBase<'a, Driver, StructLayout64>) -> Self {
369 Self {
370 inner: WindowsPebLdrDataWrapper::W64(value),
371 }
372 }
373}
374
375impl<Driver> VmiVa for WindowsPebLdrData<'_, Driver>
376where
377 Driver: VmiRead,
378 Driver::Architecture: ArchAdapter<Driver>,
379{
380 fn va(&self) -> Va {
381 match &self.inner {
382 WindowsPebLdrDataWrapper::W32(inner) => inner.va,
383 WindowsPebLdrDataWrapper::W64(inner) => inner.va,
384 }
385 }
386}
387
388impl<'a, Driver> WindowsPebLdrData<'a, Driver>
389where
390 Driver: VmiRead,
391 Driver::Architecture: ArchAdapter<Driver>,
392{
393 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
395 Self::with_kind(vmi, va, vmi.translation_root(va), WindowsWow64Kind::Native)
396 }
397
398 pub fn with_kind(
401 vmi: VmiState<'a, WindowsOs<Driver>>,
402 va: Va,
403 root: Pa,
404 kind: WindowsWow64Kind,
405 ) -> Self {
406 let inner = match kind {
407 WindowsWow64Kind::Native => WindowsPebLdrDataWrapper::native(vmi, va, root),
408 WindowsWow64Kind::X86 => WindowsPebLdrDataWrapper::w32(vmi, va, root),
409 };
410
411 Self { inner }
412 }
413
414 pub fn in_load_order_modules(
420 &self,
421 ) -> Result<
422 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
423 VmiError,
424 > {
425 self.inner.in_load_order_modules()
426 }
427
428 pub fn in_memory_order_modules(
434 &self,
435 ) -> Result<
436 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
437 VmiError,
438 > {
439 self.inner.in_memory_order_modules()
440 }
441
442 pub fn in_initialization_order_modules(
448 &self,
449 ) -> Result<
450 impl Iterator<Item = Result<WindowsUserModule<'a, Driver>, VmiError>> + use<'a, Driver>,
451 VmiError,
452 > {
453 self.inner.in_initialization_order_modules()
454 }
455}