1use vmi_core::{
2 Pa, Registers as _, Va, VmiError, VmiState, VmiVa, driver::VmiRead, os::VmiOsUserModule,
3};
4
5use super::{LdrDataTableEntry, LdrDataTableEntryLayout, WindowsWow64Kind};
6use crate::{
7 WindowsOs,
8 arch::{ArchAdapter, StructLayout, StructLayout32, StructLayout64},
9};
10
11pub struct WindowsUserModuleBase<'a, Driver, Layout>
17where
18 Driver: VmiRead,
19 Driver::Architecture: ArchAdapter<Driver>,
20 Layout: StructLayout,
21 LdrDataTableEntryLayout: LdrDataTableEntry<Layout>,
22{
23 vmi: VmiState<'a, WindowsOs<Driver>>,
25
26 va: Va,
28
29 root: Pa,
31
32 _marker: std::marker::PhantomData<Layout>,
33}
34
35impl<'a, Driver, Layout> WindowsUserModuleBase<'a, Driver, Layout>
36where
37 Driver: VmiRead,
38 Driver::Architecture: ArchAdapter<Driver>,
39 Layout: StructLayout,
40 LdrDataTableEntryLayout: LdrDataTableEntry<Layout>,
41{
42 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
44 Self {
45 vmi,
46 va,
47 root,
48 _marker: std::marker::PhantomData,
49 }
50 }
51
52 pub fn entry_point(&self) -> Result<Va, VmiError> {
58 Layout::read_va(
59 self.vmi,
60 (
61 self.va + LdrDataTableEntryLayout::OFFSET_ENTRY_POINT,
62 self.root,
63 ),
64 )
65 }
66
67 pub fn full_name(&self) -> Result<String, VmiError> {
73 Layout::read_unicode_string(
74 self.vmi,
75 (
76 self.va + LdrDataTableEntryLayout::OFFSET_FULL_DLL_NAME,
77 self.root,
78 ),
79 )
80 }
81
82 pub fn time_date_stamp(&self) -> Result<u32, VmiError> {
88 self.vmi.read_u32_in((
89 self.va + LdrDataTableEntryLayout::OFFSET_TIME_DATE_STAMP,
90 self.root,
91 ))
92 }
93
94 pub fn base_address(&self) -> Result<Va, VmiError> {
100 Layout::read_va(
101 self.vmi,
102 (
103 self.va + LdrDataTableEntryLayout::OFFSET_DLL_BASE,
104 self.root,
105 ),
106 )
107 }
108
109 pub fn size(&self) -> Result<u64, VmiError> {
115 Ok(self.vmi.read_u32_in((
116 self.va + LdrDataTableEntryLayout::OFFSET_SIZE_OF_IMAGE,
117 self.root,
118 ))? as u64)
119 }
120
121 pub fn name(&self) -> Result<String, VmiError> {
127 Layout::read_unicode_string(
128 self.vmi,
129 (
130 self.va + LdrDataTableEntryLayout::OFFSET_BASE_DLL_NAME,
131 self.root,
132 ),
133 )
134 }
135}
136
137enum WindowsUserModuleWrapper<'a, Driver>
138where
139 Driver: VmiRead,
140 Driver::Architecture: ArchAdapter<Driver>,
141{
142 W32(WindowsUserModuleBase<'a, Driver, StructLayout32>),
143 W64(WindowsUserModuleBase<'a, Driver, StructLayout64>),
144}
145
146impl<'a, Driver> WindowsUserModuleWrapper<'a, Driver>
147where
148 Driver: VmiRead,
149 Driver::Architecture: ArchAdapter<Driver>,
150{
151 fn w32(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
152 Self::W32(WindowsUserModuleBase::new(vmi, va, root))
153 }
154
155 fn w64(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
156 Self::W64(WindowsUserModuleBase::new(vmi, va, root))
157 }
158
159 fn native(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
160 match vmi.registers().address_width() {
161 4 => Self::w32(vmi, va, root),
162 8 => Self::w64(vmi, va, root),
163 _ => panic!("Unsupported address width"),
164 }
165 }
166
167 fn entry_point(&self) -> Result<Va, VmiError> {
168 match self {
169 Self::W32(inner) => inner.entry_point(),
170 Self::W64(inner) => inner.entry_point(),
171 }
172 }
173
174 fn full_name(&self) -> Result<String, VmiError> {
175 match self {
176 Self::W32(inner) => inner.full_name(),
177 Self::W64(inner) => inner.full_name(),
178 }
179 }
180
181 fn time_date_stamp(&self) -> Result<u32, VmiError> {
182 match self {
183 Self::W32(inner) => inner.time_date_stamp(),
184 Self::W64(inner) => inner.time_date_stamp(),
185 }
186 }
187
188 fn base_address(&self) -> Result<Va, VmiError> {
189 match self {
190 Self::W32(inner) => inner.base_address(),
191 Self::W64(inner) => inner.base_address(),
192 }
193 }
194
195 fn size(&self) -> Result<u64, VmiError> {
196 match self {
197 Self::W32(inner) => inner.size(),
198 Self::W64(inner) => inner.size(),
199 }
200 }
201
202 fn name(&self) -> Result<String, VmiError> {
203 match self {
204 Self::W32(inner) => inner.name(),
205 Self::W64(inner) => inner.name(),
206 }
207 }
208}
209
210pub struct WindowsUserModule<'a, Driver>
225where
226 Driver: VmiRead,
227 Driver::Architecture: ArchAdapter<Driver>,
228{
229 inner: WindowsUserModuleWrapper<'a, Driver>,
230}
231
232impl<'a, Driver> From<WindowsUserModuleBase<'a, Driver, StructLayout32>>
233 for WindowsUserModule<'a, Driver>
234where
235 Driver: VmiRead,
236 Driver::Architecture: ArchAdapter<Driver>,
237{
238 fn from(value: WindowsUserModuleBase<'a, Driver, StructLayout32>) -> Self {
239 Self {
240 inner: WindowsUserModuleWrapper::W32(value),
241 }
242 }
243}
244
245impl<'a, Driver> From<WindowsUserModuleBase<'a, Driver, StructLayout64>>
246 for WindowsUserModule<'a, Driver>
247where
248 Driver: VmiRead,
249 Driver::Architecture: ArchAdapter<Driver>,
250{
251 fn from(value: WindowsUserModuleBase<'a, Driver, StructLayout64>) -> Self {
252 Self {
253 inner: WindowsUserModuleWrapper::W64(value),
254 }
255 }
256}
257
258impl<Driver> VmiVa for WindowsUserModule<'_, Driver>
259where
260 Driver: VmiRead,
261 Driver::Architecture: ArchAdapter<Driver>,
262{
263 fn va(&self) -> Va {
264 match &self.inner {
265 WindowsUserModuleWrapper::W32(inner) => inner.va,
266 WindowsUserModuleWrapper::W64(inner) => inner.va,
267 }
268 }
269}
270
271impl<'a, Driver> WindowsUserModule<'a, Driver>
272where
273 Driver: VmiRead,
274 Driver::Architecture: ArchAdapter<Driver>,
275{
276 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va, root: Pa) -> Self {
278 Self::with_kind(vmi, va, root, WindowsWow64Kind::Native)
279 }
280
281 pub fn with_kind(
284 vmi: VmiState<'a, WindowsOs<Driver>>,
285 va: Va,
286 root: Pa,
287 kind: WindowsWow64Kind,
288 ) -> Self {
289 let inner = match kind {
290 WindowsWow64Kind::Native => WindowsUserModuleWrapper::native(vmi, va, root),
291 WindowsWow64Kind::X86 => WindowsUserModuleWrapper::w32(vmi, va, root),
292 };
293
294 Self { inner }
295 }
296
297 pub fn entry_point(&self) -> Result<Va, VmiError> {
303 self.inner.entry_point()
304 }
305
306 pub fn full_name(&self) -> Result<String, VmiError> {
312 self.inner.full_name()
313 }
314
315 pub fn time_date_stamp(&self) -> Result<u32, VmiError> {
321 self.inner.time_date_stamp()
322 }
323}
324
325impl<'a, Driver> VmiOsUserModule<'a, Driver> for WindowsUserModule<'a, Driver>
326where
327 Driver: VmiRead,
328 Driver::Architecture: ArchAdapter<Driver>,
329{
330 type Os = WindowsOs<Driver>;
331
332 fn base_address(&self) -> Result<Va, VmiError> {
338 self.inner.base_address()
339 }
340
341 fn size(&self) -> Result<u64, VmiError> {
347 self.inner.size()
348 }
349
350 fn name(&self) -> Result<String, VmiError> {
356 self.inner.name()
357 }
358}