vmi_os_windows/comps/
handle_table_entry.rs

1use vmi_core::{Architecture, Va, VmiDriver, VmiError, VmiState, VmiVa};
2
3use super::{
4    WindowsObject,
5    macros::{impl_offsets, impl_offsets_ext_v1, impl_offsets_ext_v2},
6};
7use crate::{ArchAdapter, OffsetsExt, WindowsOs};
8
9/// A Windows handle table entry.
10///
11/// A handle table entry maps a handle to a kernel object
12/// within the process's handle table.
13///
14/// # Implementation Details
15///
16/// Corresponds to `_HANDLE_TABLE_ENTRY`.
17pub struct WindowsHandleTableEntry<'a, Driver>
18where
19    Driver: VmiDriver,
20    Driver::Architecture: Architecture + ArchAdapter<Driver>,
21{
22    inner: Inner<'a, Driver>,
23}
24
25impl<Driver> VmiVa for WindowsHandleTableEntry<'_, Driver>
26where
27    Driver: VmiDriver,
28    Driver::Architecture: Architecture + ArchAdapter<Driver>,
29{
30    fn va(&self) -> Va {
31        match &self.inner {
32            Inner::V1(inner) => inner.va,
33            Inner::V2(inner) => inner.va,
34        }
35    }
36}
37
38impl<'a, Driver> WindowsHandleTableEntry<'a, Driver>
39where
40    Driver: VmiDriver,
41    Driver::Architecture: Architecture + ArchAdapter<Driver>,
42{
43    /// Creates a new Windows handle table entry.
44    pub fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
45        let inner = match vmi.underlying_os().offsets.ext() {
46            Some(OffsetsExt::V1(_)) => Inner::V1(WindowsHandleTableEntryV1::new(vmi, va)),
47            Some(OffsetsExt::V2(_)) => Inner::V2(WindowsHandleTableEntryV2::new(vmi, va)),
48            None => unimplemented!(),
49        };
50
51        Self { inner }
52    }
53
54    /// Returns the object associated with this handle.
55    ///
56    /// # Implementation Details
57    ///
58    /// Corresponds to `_OBJECT_HEADER.Object` or `_OBJECT_HEADER.ObjectPointerBits`.
59    pub fn object(&self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
60        match &self.inner {
61            Inner::V1(inner) => inner.object(),
62            Inner::V2(inner) => inner.object(),
63        }
64    }
65
66    /// Returns the handle attributes.
67    ///
68    /// # Implementation Details
69    ///
70    /// Corresponds to `_HANDLE_TABLE_ENTRY.ObAttributes` or `_HANDLE_TABLE_ENTRY.Attributes`.
71    pub fn attributes(&self) -> Result<u32, VmiError> {
72        match &self.inner {
73            Inner::V1(inner) => inner.attributes(),
74            Inner::V2(inner) => inner.attributes(),
75        }
76    }
77
78    /// Returns the granted access rights for this handle.
79    ///
80    /// # Implementation Details
81    ///
82    /// Corresponds to `_HANDLE_TABLE_ENTRY.GrantedAccess` or `_HANDLE_TABLE_ENTRY.GrantedAccessBits`.
83    pub fn granted_access(&self) -> Result<u32, VmiError> {
84        match &self.inner {
85            Inner::V1(inner) => inner.granted_access(),
86            Inner::V2(inner) => inner.granted_access(),
87        }
88    }
89}
90
91enum Inner<'a, Driver>
92where
93    Driver: VmiDriver,
94    Driver::Architecture: Architecture + ArchAdapter<Driver>,
95{
96    V1(WindowsHandleTableEntryV1<'a, Driver>),
97    V2(WindowsHandleTableEntryV2<'a, Driver>),
98}
99
100const OBJ_PROTECT_CLOSE: u64 = 0x00000001;
101const OBJ_INHERIT: u64 = 0x00000002;
102const OBJ_AUDIT_OBJECT_CLOSE: u64 = 0x00000004;
103const OBJ_HANDLE_ATTRIBUTES: u64 = OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE;
104
105struct WindowsHandleTableEntryV1<'a, Driver>
106where
107    Driver: VmiDriver,
108    Driver::Architecture: Architecture + ArchAdapter<Driver>,
109{
110    /// The VMI state.
111    vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
112
113    /// The virtual address of the `_HANDLE_TABLE_ENTRY` structure.
114    va: Va,
115}
116
117impl<'a, Driver> WindowsHandleTableEntryV1<'a, Driver>
118where
119    Driver: VmiDriver,
120    Driver::Architecture: Architecture + ArchAdapter<Driver>,
121{
122    impl_offsets!();
123    impl_offsets_ext_v1!();
124
125    fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
126        Self { vmi, va }
127    }
128
129    fn object(&self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
130        let offsets = self.offsets();
131        let offsets_ext = self.offsets_ext();
132
133        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
134        let OBJECT_HEADER = &offsets._OBJECT_HEADER;
135
136        let object = self.vmi.read_field(self.va, &HANDLE_TABLE_ENTRY.Object)?;
137        let object = Va(object & !OBJ_HANDLE_ATTRIBUTES);
138
139        if object.is_null() {
140            return Ok(None);
141        }
142
143        let object = object + OBJECT_HEADER.Body.offset();
144
145        Ok(Some(WindowsObject::new(self.vmi, object)))
146    }
147
148    fn attributes(&self) -> Result<u32, VmiError> {
149        let offsets_ext = self.offsets_ext();
150        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
151
152        let attributes = self
153            .vmi
154            .read_field(self.va, &HANDLE_TABLE_ENTRY.ObAttributes)?;
155        let attributes = (attributes & OBJ_HANDLE_ATTRIBUTES) as u32;
156
157        Ok(attributes)
158    }
159
160    fn granted_access(&self) -> Result<u32, VmiError> {
161        let offsets_ext = self.offsets_ext();
162        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
163
164        Ok(self
165            .vmi
166            .read_field(self.va, &HANDLE_TABLE_ENTRY.GrantedAccess)? as u32)
167    }
168}
169
170struct WindowsHandleTableEntryV2<'a, Driver>
171where
172    Driver: VmiDriver,
173    Driver::Architecture: Architecture + ArchAdapter<Driver>,
174{
175    /// The VMI state.
176    vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
177
178    /// The virtual address of the `_HANDLE_TABLE_ENTRY` structure.
179    va: Va,
180}
181
182impl<'a, Driver> WindowsHandleTableEntryV2<'a, Driver>
183where
184    Driver: VmiDriver,
185    Driver::Architecture: Architecture + ArchAdapter<Driver>,
186{
187    impl_offsets!();
188    impl_offsets_ext_v2!();
189
190    fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
191        Self { vmi, va }
192    }
193
194    fn object(&self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
195        let offsets = self.offsets();
196        let offsets_ext = self.offsets_ext();
197        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
198        let OBJECT_HEADER = &offsets._OBJECT_HEADER;
199
200        let object_pointer_bits = self
201            .vmi
202            .read_field(self.va, &HANDLE_TABLE_ENTRY.ObjectPointerBits)?;
203
204        let object_pointer_bits = HANDLE_TABLE_ENTRY
205            .ObjectPointerBits
206            .extract(object_pointer_bits);
207
208        if object_pointer_bits == 0 {
209            return Ok(None);
210        }
211
212        let object = Va(0xffff_0000_0000_0000 | (object_pointer_bits << 4));
213        let object = object + OBJECT_HEADER.Body.offset();
214
215        Ok(Some(WindowsObject::new(self.vmi, object)))
216    }
217
218    fn attributes(&self) -> Result<u32, VmiError> {
219        let offsets_ext = self.offsets_ext();
220        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
221
222        let attributes = self
223            .vmi
224            .read_field(self.va, &HANDLE_TABLE_ENTRY.Attributes)?;
225
226        Ok(HANDLE_TABLE_ENTRY.Attributes.extract(attributes) as u32)
227    }
228
229    fn granted_access(&self) -> Result<u32, VmiError> {
230        let offsets_ext = self.offsets_ext();
231        let HANDLE_TABLE_ENTRY = &offsets_ext._HANDLE_TABLE_ENTRY;
232
233        let granted_access = self
234            .vmi
235            .read_field(self.va, &HANDLE_TABLE_ENTRY.GrantedAccessBits)?;
236
237        Ok(HANDLE_TABLE_ENTRY.GrantedAccessBits.extract(granted_access) as u32)
238    }
239}