1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use vmi_core::{Va, VmiError, VmiState, VmiVa, driver::VmiRead};
use super::WindowsControlArea;
use crate::{ArchAdapter, WindowsOs, offset};
/// A Windows segment.
///
/// A segment describes the prototype PTEs and commit accounting that
/// back a section. One segment is shared by every control area mapping
/// the same underlying object.
///
/// # Implementation Details
///
/// Corresponds to `_SEGMENT`.
pub struct WindowsSegment<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
/// The VMI state.
vmi: VmiState<'a, WindowsOs<Driver>>,
/// Address of the `_SEGMENT` structure.
va: Va,
}
impl<Driver> VmiVa for WindowsSegment<'_, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
fn va(&self) -> Va {
self.va
}
}
impl<'a, Driver> WindowsSegment<'a, Driver>
where
Driver: VmiRead,
Driver::Architecture: ArchAdapter<Driver>,
{
/// Creates a new Windows segment.
pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
Self { vmi, va }
}
/// Returns the control area that owns this segment.
///
/// # Implementation Details
///
/// Corresponds to `_SEGMENT.ControlArea`.
pub fn control_area(&self) -> Result<WindowsControlArea<'a, Driver>, VmiError> {
let SEGMENT = offset!(self.vmi, _SEGMENT);
let control_area = self
.vmi
.read_va_native(self.va + SEGMENT.ControlArea.offset())?;
Ok(WindowsControlArea::new(self.vmi, control_area))
}
/// Returns the number of prototype PTEs covering the segment.
///
/// # Implementation Details
///
/// Corresponds to `_SEGMENT.TotalNumberOfPtes`.
pub fn total_number_of_ptes(&self) -> Result<u32, VmiError> {
let SEGMENT = offset!(self.vmi, _SEGMENT);
let total_number_of_ptes = self
.vmi
.read_u32(self.va + SEGMENT.TotalNumberOfPtes.offset())?;
Ok(total_number_of_ptes)
}
/// Returns the number of pages currently committed against the segment.
///
/// For pagefile-backed sections this is the value WinDbg's `!vad`
/// reports as "shared commit".
///
/// # Implementation Details
///
/// Corresponds to `_SEGMENT.NumberOfCommittedPages`.
pub fn number_of_committed_pages(&self) -> Result<u64, VmiError> {
let SEGMENT = offset!(self.vmi, _SEGMENT);
let number_of_committed_pages = self
.vmi
.read_address(self.va + SEGMENT.NumberOfCommittedPages.offset())?;
Ok(number_of_committed_pages)
}
/// Returns the size of the segment in bytes.
///
/// # Implementation Details
///
/// Corresponds to `_SEGMENT.SizeOfSegment`.
pub fn size_of_segment(&self) -> Result<u64, VmiError> {
let SEGMENT = offset!(self.vmi, _SEGMENT);
let size_of_segment = self
.vmi
.read_address(self.va + SEGMENT.SizeOfSegment.offset())?;
Ok(size_of_segment)
}
}