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
9pub 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 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 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 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 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 vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
112
113 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 vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
177
178 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}