vmi_os_windows/comps/object/
directory.rs

1use vmi_core::{Architecture, Va, VmiDriver, VmiError, VmiState, VmiVa};
2
3use super::{super::macros::impl_offsets, WindowsObject};
4use crate::{ArchAdapter, WindowsOs};
5
6/// A Windows directory object.
7///
8/// A directory object is a kernel-managed container that stores named objects
9/// such as events, mutexes, symbolic links, and device objects.
10///
11/// # Implementation Details
12///
13/// Corresponds to `_OBJECT_DIRECTORY`.
14pub struct WindowsDirectoryObject<'a, Driver>
15where
16    Driver: VmiDriver,
17    Driver::Architecture: Architecture + ArchAdapter<Driver>,
18{
19    /// The VMI state.
20    vmi: VmiState<'a, Driver, WindowsOs<Driver>>,
21
22    /// The virtual address of the `_OBJECT_DIRECTORY` structure.
23    va: Va,
24}
25
26impl<'a, Driver> From<WindowsDirectoryObject<'a, Driver>> for WindowsObject<'a, Driver>
27where
28    Driver: VmiDriver,
29    Driver::Architecture: Architecture + ArchAdapter<Driver>,
30{
31    fn from(value: WindowsDirectoryObject<'a, Driver>) -> Self {
32        Self::new(value.vmi, value.va)
33    }
34}
35
36impl<Driver> VmiVa for WindowsDirectoryObject<'_, Driver>
37where
38    Driver: VmiDriver,
39    Driver::Architecture: Architecture + ArchAdapter<Driver>,
40{
41    fn va(&self) -> Va {
42        self.va
43    }
44}
45
46impl<'a, Driver> WindowsDirectoryObject<'a, Driver>
47where
48    Driver: VmiDriver,
49    Driver::Architecture: Architecture + ArchAdapter<Driver>,
50{
51    impl_offsets!();
52
53    /// Creates a new Windows directory object.
54    pub fn new(vmi: VmiState<'a, Driver, WindowsOs<Driver>>, va: Va) -> Self {
55        Self { vmi, va }
56    }
57
58    /// Iterates over the objects in the directory.
59    pub fn iter(
60        &self,
61    ) -> Result<impl Iterator<Item = Result<WindowsObject<'a, Driver>, VmiError>>, VmiError> {
62        let offsets = self.offsets();
63        let OBJECT_DIRECTORY = &offsets._OBJECT_DIRECTORY;
64        let OBJECT_DIRECTORY_ENTRY = &offsets._OBJECT_DIRECTORY_ENTRY;
65
66        let mut entries = Vec::new();
67
68        for i in 0..37 {
69            let hash_bucket = self
70                .vmi
71                .read_va_native(self.va + OBJECT_DIRECTORY.HashBuckets.offset() + i * 8)?;
72
73            let mut entry = hash_bucket;
74            while !entry.is_null() {
75                let object = self
76                    .vmi
77                    .read_va_native(entry + OBJECT_DIRECTORY_ENTRY.Object.offset())?;
78
79                let object = WindowsObject::new(self.vmi, object);
80
81                entries.push(Ok(object));
82
83                entry = self
84                    .vmi
85                    .read_va_native(entry + OBJECT_DIRECTORY_ENTRY.ChainLink.offset())?;
86            }
87        }
88
89        Ok(entries.into_iter())
90    }
91
92    /// Performs a lookup in the directory.
93    pub fn lookup(
94        &self,
95        needle: impl AsRef<str>,
96    ) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
97        let offsets = self.offsets();
98        let OBJECT_DIRECTORY = &offsets._OBJECT_DIRECTORY;
99        let OBJECT_DIRECTORY_ENTRY = &offsets._OBJECT_DIRECTORY_ENTRY;
100
101        let needle = needle.as_ref();
102
103        for i in 0..37 {
104            println!("i: {}", i);
105
106            let hash_bucket = self
107                .vmi
108                .read_va_native(self.va + OBJECT_DIRECTORY.HashBuckets.offset() + i * 8)?;
109
110            let mut entry = hash_bucket;
111            while !entry.is_null() {
112                println!("  entry: {}", entry);
113
114                let object = self
115                    .vmi
116                    .read_va_native(entry + OBJECT_DIRECTORY_ENTRY.Object.offset())?;
117                println!("    object: {}", object);
118
119                let hash_value = self
120                    .vmi
121                    .read_u32(entry + OBJECT_DIRECTORY_ENTRY.HashValue.offset())?;
122                println!("    hash_value: {}", hash_value);
123
124                let object = WindowsObject::new(self.vmi, object);
125
126                if let Some(name) = object.name()? {
127                    println!("    name: {name}");
128
129                    if name == needle {
130                        return Ok(Some(object));
131                    }
132                }
133
134                entry = self
135                    .vmi
136                    .read_va_native(entry + OBJECT_DIRECTORY_ENTRY.ChainLink.offset())?;
137            }
138        }
139
140        Ok(None)
141    }
142}