Skip to main content

vmi_os_windows/comps/
handle_table_entry.rs

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