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
6pub 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 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 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 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 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 vmi: VmiState<'a, WindowsOs<Driver>>,
109
110 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 vmi: VmiState<'a, WindowsOs<Driver>>,
166
167 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}