vmi_os_windows/comps/object/
section.rs1use once_cell::unsync::OnceCell;
2use vmi_core::{Architecture, Va, VmiDriver, VmiError, VmiState, VmiVa};
3
4use super::{
5 super::{
6 WindowsControlArea,
7 macros::{impl_offsets, impl_offsets_ext_v1, impl_offsets_ext_v2},
8 },
9 WindowsFileObject, WindowsObject,
10};
11use crate::{ArchAdapter, OffsetsExt, WindowsOs};
12
13pub struct WindowsSectionObject<'a, Driver>
23where
24 Driver: VmiDriver,
25 Driver::Architecture: Architecture + ArchAdapter<Driver>,
26{
27 inner: Inner<'a, Driver>,
28}
29
30impl<'a, Driver> From<WindowsSectionObject<'a, Driver>> for WindowsObject<'a, Driver>
31where
32 Driver: VmiDriver,
33 Driver::Architecture: Architecture + ArchAdapter<Driver>,
34{
35 fn from(value: WindowsSectionObject<'a, Driver>) -> Self {
36 let (vmi, va) = match value.inner {
37 Inner::V1(inner) => (inner.vmi, inner.va),
38 Inner::V2(inner) => (inner.vmi, inner.va),
39 };
40
41 Self::new(vmi, va)
42 }
43}
44
45impl<Driver> VmiVa for WindowsSectionObject<'_, Driver>
46where
47 Driver: VmiDriver,
48 Driver::Architecture: Architecture + ArchAdapter<Driver>,
49{
50 fn va(&self) -> Va {
51 match &self.inner {
52 Inner::V1(inner) => inner.va,
53 Inner::V2(inner) => inner.va,
54 }
55 }
56}
57
58impl<'a, Driver> WindowsSectionObject<'a, Driver>
59where
60 Driver: VmiDriver,
61 Driver::Architecture: Architecture + ArchAdapter<Driver>,
62{
63 pub fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
65 let inner = match vmi.underlying_os().offsets.ext() {
66 Some(OffsetsExt::V1(_)) => Inner::V1(WindowsSectionObjectV1::new(vmi, va)),
67 Some(OffsetsExt::V2(_)) => Inner::V2(WindowsSectionObjectV2::new(vmi, va)),
68 None => unimplemented!(),
69 };
70
71 Self { inner }
72 }
73
74 pub fn start(&self) -> Result<Va, VmiError> {
81 match &self.inner {
82 Inner::V1(inner) => inner.start(),
83 Inner::V2(inner) => inner.start(),
84 }
85 }
86
87 pub fn end(&self) -> Result<Va, VmiError> {
94 match &self.inner {
95 Inner::V1(inner) => inner.end(),
96 Inner::V2(inner) => inner.end(),
97 }
98 }
99
100 pub fn size(&self) -> Result<u64, VmiError> {
106 match &self.inner {
107 Inner::V1(inner) => inner.size(),
108 Inner::V2(inner) => inner.size(),
109 }
110 }
111
112 pub fn flags(&self) -> Result<u64, VmiError> {
118 match &self.inner {
119 Inner::V1(inner) => inner.flags(),
120 Inner::V2(inner) => inner.flags(),
121 }
122 }
123
124 pub fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
131 match &self.inner {
132 Inner::V1(inner) => inner.file_object(),
133 Inner::V2(inner) => inner.file_object(),
134 }
135 }
136
137 pub fn full_path(&self) -> Result<Option<String>, VmiError> {
143 match self.file_object() {
144 Ok(Some(file_object)) => Ok(Some(file_object.full_path()?)),
145 _ => Ok(None),
146 }
147 }
148}
149
150enum Inner<'a, Driver>
152where
153 Driver: VmiDriver,
154 Driver::Architecture: Architecture + ArchAdapter<Driver>,
155{
156 V1(WindowsSectionObjectV1<'a, Driver>),
157 V2(WindowsSectionObjectV2<'a, Driver>),
158}
159
160struct WindowsSectionObjectV1<'a, Driver>
162where
163 Driver: VmiDriver,
164 Driver::Architecture: Architecture + ArchAdapter<Driver>,
165{
166 vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
168
169 va: Va,
171
172 segment: OnceCell<Va>,
174}
175
176impl<'a, Driver> WindowsSectionObjectV1<'a, Driver>
177where
178 Driver: VmiDriver,
179 Driver::Architecture: Architecture + ArchAdapter<Driver>,
180{
181 impl_offsets!();
182 impl_offsets_ext_v1!();
183
184 fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
185 Self {
186 vmi,
187 va,
188 segment: OnceCell::new(),
189 }
190 }
191
192 fn start(&self) -> Result<Va, VmiError> {
193 let offsets_ext = self.offsets_ext();
194 let SECTION_OBJECT = &offsets_ext._SECTION_OBJECT;
195
196 let starting_vpn = self.vmi.read_field(self.va, &SECTION_OBJECT.StartingVa)?;
197
198 Ok(Va(starting_vpn << 12))
199 }
200
201 fn end(&self) -> Result<Va, VmiError> {
202 let offsets_ext = self.offsets_ext();
203 let SECTION_OBJECT = &offsets_ext._SECTION_OBJECT;
204
205 let ending_vpn = self.vmi.read_field(self.va, &SECTION_OBJECT.EndingVa)?;
206
207 Ok(Va((ending_vpn + 1) << 12))
208 }
209
210 fn size(&self) -> Result<u64, VmiError> {
211 let offsets_ext = self.offsets_ext();
212 let SEGMENT_OBJECT = &offsets_ext._SEGMENT_OBJECT;
213
214 let size = self
215 .vmi
216 .read_field(self.segment()?, &SEGMENT_OBJECT.SizeOfSegment)?;
217
218 Ok(size)
219 }
220
221 fn flags(&self) -> Result<u64, VmiError> {
222 let offsets_ext = self.offsets_ext();
223 let SEGMENT_OBJECT = &offsets_ext._SEGMENT_OBJECT;
224
225 let flags = Va(self
226 .vmi
227 .read_field(self.segment()?, &SEGMENT_OBJECT.MmSectionFlags)?);
228
229 Ok(self.vmi.read_u32(flags)? as u64)
230 }
231
232 fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
233 let offsets = self.offsets();
234 let offsets_ext = self.offsets_ext();
235 let SEGMENT_OBJECT = &offsets_ext._SEGMENT_OBJECT;
236 let MMSECTION_FLAGS = &offsets._MMSECTION_FLAGS;
237
238 let flags = self.flags()?;
239 let file = MMSECTION_FLAGS.File.extract(flags) != 0;
240
241 if !file {
242 return Ok(None);
243 }
244
245 let control_area = Va(self
246 .vmi
247 .read_field(self.segment()?, &SEGMENT_OBJECT.ControlArea)?);
248
249 WindowsControlArea::new(self.vmi, control_area).file_object()
250 }
251
252 fn segment(&self) -> Result<Va, VmiError> {
253 self.segment
254 .get_or_try_init(|| {
255 let offsets_ext = self.offsets_ext();
256 let SECTION_OBJECT = &offsets_ext._SECTION_OBJECT;
257
258 let segment = self.vmi.read_field(self.va, &SECTION_OBJECT.Segment)?;
259
260 Ok(Va(segment))
261 })
262 .copied()
263 }
264}
265
266struct WindowsSectionObjectV2<'a, Driver>
267where
268 Driver: VmiDriver,
269 Driver::Architecture: Architecture + ArchAdapter<Driver>,
270{
271 vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
273
274 va: Va,
276}
277
278impl<'a, Driver> WindowsSectionObjectV2<'a, Driver>
279where
280 Driver: VmiDriver,
281 Driver::Architecture: Architecture + ArchAdapter<Driver>,
282{
283 impl_offsets!();
284 impl_offsets_ext_v2!();
285
286 fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
287 Self { vmi, va }
288 }
289
290 fn start(&self) -> Result<Va, VmiError> {
291 let offsets_ext = self.offsets_ext();
292 let SECTION = &offsets_ext._SECTION;
293
294 let starting_vpn = self.vmi.read_field(self.va, &SECTION.StartingVpn)?;
295
296 Ok(Va(starting_vpn << 12))
297 }
298
299 fn end(&self) -> Result<Va, VmiError> {
300 let offsets_ext = self.offsets_ext();
301 let SECTION = &offsets_ext._SECTION;
302
303 let ending_vpn = self.vmi.read_field(self.va, &SECTION.EndingVpn)?;
304
305 Ok(Va((ending_vpn + 1) << 12))
306 }
307
308 fn size(&self) -> Result<u64, VmiError> {
309 let offsets_ext = self.offsets_ext();
310 let SECTION = &offsets_ext._SECTION;
311
312 self.vmi.read_field(self.va, &SECTION.SizeOfSection)
313 }
314
315 fn flags(&self) -> Result<u64, VmiError> {
316 let offsets_ext = self.offsets_ext();
317 let SECTION = &offsets_ext._SECTION;
318
319 self.vmi.read_field(self.va, &SECTION.Flags)
320 }
321
322 fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
323 let offsets = self.offsets();
324 let offsets_ext = self.offsets_ext();
325 let MMSECTION_FLAGS = &offsets._MMSECTION_FLAGS;
326 let SECTION = &offsets_ext._SECTION;
327
328 let flags = self.flags()?;
329 let file = MMSECTION_FLAGS.File.extract(flags) != 0;
330
331 if !file {
332 return Ok(None);
333 }
334
335 let control_area = Va(self.vmi.read_field(self.va, &SECTION.ControlArea)?);
358
359 if control_area.0 & 0x3 != 0 {
360 let file_object = control_area;
361 return Ok(Some(WindowsFileObject::new(self.vmi, file_object)));
362 }
363
364 WindowsControlArea::new(self.vmi, control_area).file_object()
365 }
366}