vmi_os_windows/comps/object/
section.rs1use once_cell::unsync::OnceCell;
2use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
3
4use super::{
5 super::WindowsControlArea, FromWindowsObject, WindowsFileObject, WindowsObject,
6 WindowsObjectTypeKind,
7};
8use crate::{ArchAdapter, OffsetsExt, WindowsOs, offset, offset_ext_v1, offset_ext_v2};
9
10pub struct WindowsSectionObject<'a, Driver>
20where
21 Driver: VmiRead,
22 Driver::Architecture: ArchAdapter<Driver>,
23{
24 inner: Inner<'a, Driver>,
25}
26
27impl<'a, Driver> From<WindowsSectionObject<'a, Driver>> for WindowsObject<'a, Driver>
28where
29 Driver: VmiRead,
30 Driver::Architecture: ArchAdapter<Driver>,
31{
32 fn from(value: WindowsSectionObject<'a, Driver>) -> Self {
33 let (vmi, va) = match value.inner {
34 Inner::V1(inner) => (inner.vmi, inner.va),
35 Inner::V2(inner) => (inner.vmi, inner.va),
36 };
37
38 Self::new(vmi, va)
39 }
40}
41
42impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsSectionObject<'a, Driver>
43where
44 Driver: VmiRead,
45 Driver::Architecture: ArchAdapter<Driver>,
46{
47 fn from_object(object: WindowsObject<'a, Driver>) -> Result<Option<Self>, VmiError> {
48 match object.type_kind()? {
49 Some(WindowsObjectTypeKind::Section) => Ok(Some(Self::new(object.vmi, object.va))),
50 _ => Ok(None),
51 }
52 }
53}
54
55impl<Driver> VmiVa for WindowsSectionObject<'_, Driver>
56where
57 Driver: VmiRead,
58 Driver::Architecture: ArchAdapter<Driver>,
59{
60 fn va(&self) -> Va {
61 match &self.inner {
62 Inner::V1(inner) => inner.va,
63 Inner::V2(inner) => inner.va,
64 }
65 }
66}
67
68impl<'a, Driver> WindowsSectionObject<'a, Driver>
69where
70 Driver: VmiRead,
71 Driver::Architecture: ArchAdapter<Driver>,
72{
73 pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
75 let inner = match vmi.underlying_os().offsets.ext() {
76 Some(OffsetsExt::V1(_)) => Inner::V1(WindowsSectionObjectV1::new(vmi, va)),
77 Some(OffsetsExt::V2(_)) => Inner::V2(WindowsSectionObjectV2::new(vmi, va)),
78 None => unimplemented!(),
79 };
80
81 Self { inner }
82 }
83
84 pub fn start(&self) -> Result<Va, VmiError> {
91 match &self.inner {
92 Inner::V1(inner) => inner.start(),
93 Inner::V2(inner) => inner.start(),
94 }
95 }
96
97 pub fn end(&self) -> Result<Va, VmiError> {
104 match &self.inner {
105 Inner::V1(inner) => inner.end(),
106 Inner::V2(inner) => inner.end(),
107 }
108 }
109
110 pub fn size(&self) -> Result<u64, VmiError> {
116 match &self.inner {
117 Inner::V1(inner) => inner.size(),
118 Inner::V2(inner) => inner.size(),
119 }
120 }
121
122 pub fn flags(&self) -> Result<u64, VmiError> {
128 match &self.inner {
129 Inner::V1(inner) => inner.flags(),
130 Inner::V2(inner) => inner.flags(),
131 }
132 }
133
134 pub fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
141 match &self.inner {
142 Inner::V1(inner) => inner.file_object(),
143 Inner::V2(inner) => inner.file_object(),
144 }
145 }
146
147 pub fn full_path(&self) -> Result<Option<String>, VmiError> {
153 match self.file_object() {
154 Ok(Some(file_object)) => Ok(Some(file_object.full_path()?)),
155 _ => Ok(None),
156 }
157 }
158}
159
160enum Inner<'a, Driver>
162where
163 Driver: VmiRead,
164 Driver::Architecture: ArchAdapter<Driver>,
165{
166 V1(WindowsSectionObjectV1<'a, Driver>),
167 V2(WindowsSectionObjectV2<'a, Driver>),
168}
169
170struct WindowsSectionObjectV1<'a, Driver>
172where
173 Driver: VmiRead,
174 Driver::Architecture: ArchAdapter<Driver>,
175{
176 vmi: VmiState<'a, WindowsOs<Driver>>,
178
179 va: Va,
181
182 segment: OnceCell<Va>,
184}
185
186impl<'a, Driver> WindowsSectionObjectV1<'a, Driver>
187where
188 Driver: VmiRead,
189 Driver::Architecture: ArchAdapter<Driver>,
190{
191 fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
192 Self {
193 vmi,
194 va,
195 segment: OnceCell::new(),
196 }
197 }
198
199 fn start(&self) -> Result<Va, VmiError> {
200 let SECTION_OBJECT = offset_ext_v1!(self.vmi, _SECTION_OBJECT);
201
202 let starting_vpn = self.vmi.read_field(self.va, &SECTION_OBJECT.StartingVa)?;
203
204 Ok(Va(starting_vpn << 12))
205 }
206
207 fn end(&self) -> Result<Va, VmiError> {
208 let SECTION_OBJECT = offset_ext_v1!(self.vmi, _SECTION_OBJECT);
209
210 let ending_vpn = self.vmi.read_field(self.va, &SECTION_OBJECT.EndingVa)?;
211
212 Ok(Va((ending_vpn + 1) << 12))
213 }
214
215 fn size(&self) -> Result<u64, VmiError> {
216 let SEGMENT_OBJECT = offset_ext_v1!(self.vmi, _SEGMENT_OBJECT);
217
218 let size = self
219 .vmi
220 .read_field(self.segment()?, &SEGMENT_OBJECT.SizeOfSegment)?;
221
222 Ok(size)
223 }
224
225 fn flags(&self) -> Result<u64, VmiError> {
226 let SEGMENT_OBJECT = offset_ext_v1!(self.vmi, _SEGMENT_OBJECT);
227
228 let flags = Va(self
229 .vmi
230 .read_field(self.segment()?, &SEGMENT_OBJECT.MmSectionFlags)?);
231
232 Ok(self.vmi.read_u32(flags)? as u64)
233 }
234
235 fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
236 let SEGMENT_OBJECT = offset_ext_v1!(self.vmi, _SEGMENT_OBJECT);
237 let MMSECTION_FLAGS = offset!(self.vmi, _MMSECTION_FLAGS);
238
239 let flags = self.flags()?;
240 let file = MMSECTION_FLAGS.File.extract(flags) != 0;
241
242 if !file {
243 return Ok(None);
244 }
245
246 let control_area = Va(self
247 .vmi
248 .read_field(self.segment()?, &SEGMENT_OBJECT.ControlArea)?);
249
250 WindowsControlArea::new(self.vmi, control_area).file_object()
251 }
252
253 fn segment(&self) -> Result<Va, VmiError> {
254 self.segment
255 .get_or_try_init(|| {
256 let SECTION_OBJECT = offset_ext_v1!(self.vmi, _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: VmiRead,
269 Driver::Architecture: ArchAdapter<Driver>,
270{
271 vmi: VmiState<'a, WindowsOs<Driver>>,
273
274 va: Va,
276}
277
278impl<'a, Driver> WindowsSectionObjectV2<'a, Driver>
279where
280 Driver: VmiRead,
281 Driver::Architecture: ArchAdapter<Driver>,
282{
283 fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
284 Self { vmi, va }
285 }
286
287 fn start(&self) -> Result<Va, VmiError> {
288 let SECTION = offset_ext_v2!(self.vmi, _SECTION);
289
290 let starting_vpn = self.vmi.read_field(self.va, &SECTION.StartingVpn)?;
291
292 Ok(Va(starting_vpn << 12))
293 }
294
295 fn end(&self) -> Result<Va, VmiError> {
296 let SECTION = offset_ext_v2!(self.vmi, _SECTION);
297
298 let ending_vpn = self.vmi.read_field(self.va, &SECTION.EndingVpn)?;
299
300 Ok(Va((ending_vpn + 1) << 12))
301 }
302
303 fn size(&self) -> Result<u64, VmiError> {
304 let SECTION = offset_ext_v2!(self.vmi, _SECTION);
305
306 self.vmi.read_field(self.va, &SECTION.SizeOfSection)
307 }
308
309 fn flags(&self) -> Result<u64, VmiError> {
310 let SECTION = offset_ext_v2!(self.vmi, _SECTION);
311
312 self.vmi.read_field(self.va, &SECTION.Flags)
313 }
314
315 fn file_object(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
316 let MMSECTION_FLAGS = offset!(self.vmi, _MMSECTION_FLAGS);
317 let SECTION = offset_ext_v2!(self.vmi, _SECTION);
318
319 let flags = self.flags()?;
320 let file = MMSECTION_FLAGS.File.extract(flags) != 0;
321
322 if !file {
323 return Ok(None);
324 }
325
326 let control_area = Va(self.vmi.read_field(self.va, &SECTION.ControlArea)?);
349
350 if control_area.0 & 0x3 != 0 {
351 let file_object = control_area;
352 return Ok(Some(WindowsFileObject::new(self.vmi, file_object)));
353 }
354
355 WindowsControlArea::new(self.vmi, control_area).file_object()
356 }
357}