wraith/structures/
ldr.rs

1//! LDR_DATA_TABLE_ENTRY and PEB_LDR_DATA structures
2
3#[cfg(all(not(feature = "std"), feature = "alloc"))]
4use alloc::string::String;
5
6#[cfg(feature = "std")]
7use std::string::String;
8
9use super::list_entry::ListEntry;
10use super::unicode_string::UnicodeString;
11use crate::arch::NativePtr;
12
13/// PEB_LDR_DATA - contains the module lists
14#[repr(C)]
15pub struct PebLdrData {
16    pub length: u32,
17    pub initialized: u8,
18    pub ss_handle: NativePtr,
19    pub in_load_order_module_list: ListEntry,
20    pub in_memory_order_module_list: ListEntry,
21    pub in_initialization_order_module_list: ListEntry,
22    pub entry_in_progress: NativePtr,
23    pub shutdown_in_progress: u8,
24    pub shutdown_thread_id: NativePtr,
25}
26
27/// LDR_DATA_TABLE_ENTRY - represents a loaded module
28///
29/// this is a simplified version; full structure has more fields
30/// that vary by Windows version
31#[repr(C)]
32pub struct LdrDataTableEntry {
33    pub in_load_order_links: ListEntry,
34    pub in_memory_order_links: ListEntry,
35    pub in_initialization_order_links: ListEntry,
36    pub dll_base: NativePtr,
37    pub entry_point: NativePtr,
38    pub size_of_image: u32,
39    pub full_dll_name: UnicodeString,
40    pub base_dll_name: UnicodeString,
41    // additional fields vary by Windows version
42    // these are accessed via offsets when needed
43}
44
45impl LdrDataTableEntry {
46    /// get module base address
47    pub fn base(&self) -> usize {
48        self.dll_base as usize
49    }
50
51    /// get module size
52    pub fn size(&self) -> usize {
53        self.size_of_image as usize
54    }
55
56    /// get entry point address
57    pub fn entry_point(&self) -> usize {
58        self.entry_point as usize
59    }
60
61    /// get full path as String
62    ///
63    /// # Safety
64    /// full_dll_name buffer must be valid
65    pub unsafe fn full_name(&self) -> String {
66        unsafe { self.full_dll_name.to_string() }
67    }
68
69    /// get base name (filename only) as String
70    ///
71    /// # Safety
72    /// base_dll_name buffer must be valid
73    pub unsafe fn base_name(&self) -> String {
74        unsafe { self.base_dll_name.to_string() }
75    }
76
77    /// check if address is within this module
78    pub fn contains_address(&self, addr: usize) -> bool {
79        let base = self.base();
80        addr >= base && addr < base + self.size()
81    }
82
83    /// check if this module matches a name (case-insensitive)
84    ///
85    /// # Safety
86    /// name buffers must be valid
87    pub unsafe fn matches_name(&self, name: &str) -> bool {
88        unsafe { self.base_dll_name.eq_ignore_case(name) }
89    }
90}
91
92/// offset of InLoadOrderLinks within LDR_DATA_TABLE_ENTRY
93pub const IN_LOAD_ORDER_LINKS_OFFSET: usize = 0;
94
95/// offset of InMemoryOrderLinks within LDR_DATA_TABLE_ENTRY
96#[cfg(target_arch = "x86_64")]
97pub const IN_MEMORY_ORDER_LINKS_OFFSET: usize = 0x10;
98
99#[cfg(target_arch = "x86")]
100pub const IN_MEMORY_ORDER_LINKS_OFFSET: usize = 0x08;
101
102/// offset of InInitializationOrderLinks within LDR_DATA_TABLE_ENTRY
103#[cfg(target_arch = "x86_64")]
104pub const IN_INITIALIZATION_ORDER_LINKS_OFFSET: usize = 0x20;
105
106#[cfg(target_arch = "x86")]
107pub const IN_INITIALIZATION_ORDER_LINKS_OFFSET: usize = 0x10;