forensic_rs/traits/registry/
mod.rs1use crate::{
2 err::{ForensicError, ForensicResult}, utils::time::Filetime
3};
4
5use super::vfs::{VirtualFile, VirtualFileSystem};
6
7pub const HKCR : RegHiveKey = RegHiveKey::HkeyClassesRoot;
8pub const HKC : RegHiveKey = RegHiveKey::HkeyCurrentConfig;
9pub const HKCU : RegHiveKey = RegHiveKey::HkeyCurrentUser;
10pub const HKLM : RegHiveKey = RegHiveKey::HkeyLocalMachine;
11pub const HKU : RegHiveKey = RegHiveKey::HkeyUsers;
12
13pub mod extra;
14
15#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug)]
16pub enum RegHiveKey {
17 HkeyClassesRoot,
18 HkeyCurrentConfig,
19 HkeyCurrentUser,
20 HkeyDynData,
21 HkeyLocalMachine,
22 KkeyPerformanceData,
23 HkeyPerformanceNlstext,
24 HkeyPerformanceText,
25 HkeyUsers,
26 Hkey(isize),
27}
28
29#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
30pub enum RegValue {
31 Binary(Vec<u8>),
32 MultiSZ(Vec<String>),
33 ExpandSZ(String),
34 SZ(String),
35 DWord(u32),
36 QWord(u64),
37}
38
39impl RegValue {
40 pub fn from_str(v : &str) -> RegValue {
41 RegValue::SZ(v.to_string())
42 }
43 pub fn from_string(v : String) -> RegValue {
44 RegValue::SZ(v.clone())
45 }
46 pub fn from_u32(v : u32) -> RegValue {
47 RegValue::DWord(v)
48 }
49 pub fn from_u64(v : u64) -> RegValue {
50 RegValue::QWord(v)
51 }
52}
53
54impl Into<RegValue> for String {
55 fn into(self) -> RegValue {
56 RegValue::SZ(self)
57 }
58}
59
60impl Into<RegValue> for &str {
61 fn into(self) -> RegValue {
62 RegValue::SZ(self.to_string())
63 }
64}
65
66impl Into<RegValue> for u32 {
67 fn into(self) -> RegValue {
68 RegValue::DWord(self)
69 }
70}
71
72impl Into<RegValue> for u64 {
73 fn into(self) -> RegValue {
74 RegValue::QWord(self)
75 }
76}
77impl Into<RegValue> for i32 {
78 fn into(self) -> RegValue {
79 RegValue::DWord(self as u32)
80 }
81}
82
83impl Into<RegValue> for i64 {
84 fn into(self) -> RegValue {
85 RegValue::QWord(self as u64)
86 }
87}
88impl Into<RegValue> for usize {
89 fn into(self) -> RegValue {
90 #[cfg(target_pointer_width="32")]
91 {
92 RegValue::DWord(self as u32)
93 }
94 #[cfg(target_pointer_width="16")]
95 {
96 RegValue::DWord(self as u32)
97 }
98 #[cfg(target_pointer_width="64")]
99 {
100 RegValue::QWord(self as u64)
101 }
102 }
103}
104
105impl Into<RegValue> for Vec<u8> {
106 fn into(self) -> RegValue {
107 RegValue::Binary(self)
108 }
109}
110
111impl From<Vec<String>> for RegValue {
112 fn from(value: Vec<String>) -> Self {
113 RegValue::MultiSZ(value)
114 }
115}
116impl From<&[u8]> for RegValue {
117 fn from(value: &[u8]) -> Self {
118 let mut vc = Vec::with_capacity(value.len());
119 for v in value {
120 vc.push(*v);
121 }
122 RegValue::Binary(vc)
123 }
124}
125impl From<&[String]> for RegValue {
126 fn from(value: &[String]) -> Self {
127 let mut vc = Vec::with_capacity(value.len());
128 for v in value {
129 vc.push(v.clone());
130 }
131 RegValue::MultiSZ(vc)
132 }
133}
134impl From<&[&String]> for RegValue {
135 fn from(value: &[&String]) -> Self {
136 let mut vc = Vec::with_capacity(value.len());
137 for &v in value {
138 vc.push(v.clone());
139 }
140 RegValue::MultiSZ(vc)
141 }
142}
143impl From<&[&str]> for RegValue {
144 fn from(value: &[&str]) -> Self {
145 let mut vc = Vec::with_capacity(value.len());
146 for &v in value {
147 vc.push(v.to_string());
148 }
149 RegValue::MultiSZ(vc)
150 }
151}
152
153impl TryFrom<RegValue> for String {
154 type Error = ForensicError;
155 fn try_from(value : RegValue) -> Result<Self, Self::Error> {
156 match value {
157 RegValue::MultiSZ(v) => Ok(v.join("\n")),
158 RegValue::ExpandSZ(v) => Ok(v),
159 RegValue::SZ(v) => Ok(v),
160 _ => Err(ForensicError::CastError),
161 }
162 }
163}
164impl TryFrom<RegValue> for u32 {
165 type Error = ForensicError;
166 fn try_from(value : RegValue) -> Result<Self, Self::Error> {
167 match value {
168 RegValue::DWord(v) => Ok(v),
169 RegValue::QWord(v) => Ok(v as u32),
170 _ => Err(ForensicError::CastError),
171 }
172 }
173}
174impl TryFrom<RegValue> for u64 {
175 type Error = ForensicError;
176 fn try_from(value : RegValue) -> Result<Self, Self::Error> {
177 match value {
178 RegValue::DWord(v) => Ok(v as u64),
179 RegValue::QWord(v) => Ok(v),
180 _ => Err(ForensicError::CastError),
181 }
182 }
183}
184impl TryFrom<RegValue> for Vec<u8> {
185 type Error = ForensicError;
186 fn try_from(value : RegValue) -> Result<Self, Self::Error> {
187 match value {
188 RegValue::Binary(v) => Ok(v),
189 _ => Err(ForensicError::CastError),
190 }
191 }
192}
193
194#[derive(Clone, Copy, Debug, Default)]
195pub struct RegistryKeyInfo {
196 pub subkeys : u32,
197 pub max_subkey_name_length : u32,
198 pub values : u32,
199 pub max_value_name_length : u32,
200 pub max_value_length : u32,
201 pub last_write_time : Filetime
202
203}
204
205pub trait RegistryReader {
207 fn from_file(&self, file: Box<dyn VirtualFile>) -> ForensicResult<Box<dyn RegistryReader>>;
209 fn from_fs(&self, fs: Box<dyn VirtualFileSystem>) -> ForensicResult<Box<dyn RegistryReader>>;
211 fn open_key(&self, hkey: RegHiveKey, key_name: &str) -> ForensicResult<RegHiveKey>;
214 fn read_value(&self, hkey: RegHiveKey, value_name: &str) -> ForensicResult<RegValue>;
215 fn enumerate_values(&self, hkey: RegHiveKey) -> ForensicResult<Vec<String>>;
216 fn enumerate_keys(&self, hkey: RegHiveKey) -> ForensicResult<Vec<String>>;
217 fn key_at(&self, hkey: RegHiveKey, pos: u32) -> ForensicResult<String>;
218 fn value_at(&self, hkey: RegHiveKey, pos: u32) -> ForensicResult<String>;
219 fn key_info(&self, hkey: RegHiveKey) -> ForensicResult<RegistryKeyInfo>;
221 #[allow(unused_variables)]
223 fn close_key(&self, hkey: RegHiveKey) {}
224
225 fn get_system_root(&self) -> ForensicResult<String> {
227 let key = self.open_key(
228 RegHiveKey::HkeyLocalMachine,
229 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
230 )?;
231 let value = self.read_value(key, "SystemRoot")?;
232 Ok(value.try_into()?)
233 }
234
235 fn list_users(&self) -> ForensicResult<Vec<String>> {
236 let mut users = self.enumerate_keys(RegHiveKey::HkeyUsers)?;
237 users.retain(|v| v.starts_with("S-") && !v.ends_with("_Classes"));
238 Ok(users)
239 }
240
241 fn windows_build(&self) -> ForensicResult<u32> {
243 let key = self.open_key(
244 RegHiveKey::HkeyLocalMachine,
245 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
246 )?;
247 let value = self.read_value(key, "CurrentBuild")?;
248 Ok(value.try_into()?)
249 }
250}
251
252pub fn auto_close_key<F, T>(reader : &dyn RegistryReader, key : RegHiveKey, operation : F) -> ForensicResult<T> where
276 F: FnOnce() -> ForensicResult<T> {
277 let result = operation();
278 reader.close_key(key);
279 result
280 }
281
282#[cfg(test)]
283mod reg_value {
284 use crate::{err::ForensicResult, traits::registry::{RegistryKeyInfo, RegistryReader}};
285
286 use super::RegValue;
287
288 #[test]
289 fn should_convert_using_try_into() {
290 let _: String = RegValue::SZ(format!("String RegValue"))
291 .try_into()
292 .expect("Must convert values");
293 let _: String = RegValue::MultiSZ(vec![format!("String RegValue")])
294 .try_into()
295 .expect("Must convert values");
296 let _: String = RegValue::ExpandSZ(format!("String RegValue"))
297 .try_into()
298 .expect("Must convert values");
299
300 let _ = TryInto::<u32>::try_into(RegValue::ExpandSZ(format!("String RegValue")))
301 .expect_err("Should return error");
302 let _ = TryInto::<u64>::try_into(RegValue::ExpandSZ(format!("String RegValue")))
303 .expect_err("Should return error");
304 let _ = TryInto::<Vec<u8>>::try_into(RegValue::ExpandSZ(format!("String RegValue")))
305 .expect_err("Should return error");
306
307 let _: u32 = RegValue::DWord(123)
308 .try_into()
309 .expect("Must convert values");
310 let _: u64 = RegValue::DWord(123)
311 .try_into()
312 .expect("Must convert values");
313
314 let _ = TryInto::<String>::try_into(RegValue::DWord(123)).expect_err("Should return error");
315 let _ =
316 TryInto::<Vec<u8>>::try_into(RegValue::DWord(123)).expect_err("Should return error");
317
318 let _: u32 = RegValue::QWord(123)
319 .clone()
320 .try_into()
321 .expect("Must convert values");
322 let _: u64 = RegValue::QWord(123)
323 .try_into()
324 .expect("Must convert values");
325
326 let _ = TryInto::<String>::try_into(RegValue::QWord(123)).expect_err("Should return error");
327 let _ =
328 TryInto::<Vec<u8>>::try_into(RegValue::QWord(123)).expect_err("Should return error");
329
330 let _: Vec<u8> = RegValue::Binary((1..255).collect())
331 .try_into()
332 .expect("Must convert values");
333 let _ = TryInto::<u32>::try_into(RegValue::Binary((1..255).collect()))
334 .expect_err("Should return error");
335 let _ = TryInto::<u32>::try_into(RegValue::Binary((1..255).collect()))
336 .expect_err("Should return error");
337 let _ = TryInto::<u32>::try_into(RegValue::Binary((1..255).collect()))
338 .expect_err("Should return error");
339 }
340
341 #[test]
342 fn should_generate_dummy_registry_reader() {
343 struct RegReader {}
344 impl RegistryReader for RegReader {
345 fn from_file(
346 &self,
347 _file: Box<dyn crate::traits::vfs::VirtualFile>,
348 ) -> crate::err::ForensicResult<Box<dyn RegistryReader>> {
349 Ok(Box::new(RegReader{}))
350 }
351
352 fn from_fs(
353 &self,
354 _fs: Box<dyn crate::traits::vfs::VirtualFileSystem>,
355 ) -> crate::err::ForensicResult<Box<dyn RegistryReader>> {
356 Ok(Box::new(RegReader{}))
357 }
358
359 fn open_key(
360 &self,
361 _hkey: crate::traits::registry::RegHiveKey,
362 _key_name: &str,
363 ) -> crate::err::ForensicResult<crate::traits::registry::RegHiveKey> {
364 Ok(crate::traits::registry::RegHiveKey::HkeyClassesRoot)
365 }
366
367 fn read_value(
368 &self,
369 _hkey: crate::traits::registry::RegHiveKey,
370 _value_name: &str,
371 ) -> crate::err::ForensicResult<RegValue> {
372 Ok(RegValue::SZ(format!("123")))
373 }
374
375 fn enumerate_values(
376 &self,
377 _hkey: crate::traits::registry::RegHiveKey,
378 ) -> crate::err::ForensicResult<Vec<String>> {
379 Ok(vec![format!("123")])
380 }
381
382 fn enumerate_keys(
383 &self,
384 _hkey: crate::traits::registry::RegHiveKey,
385 ) -> crate::err::ForensicResult<Vec<String>> {
386 Ok(vec![format!("123")])
387 }
388
389 fn key_at(
390 &self,
391 _hkey: crate::traits::registry::RegHiveKey,
392 _pos: u32,
393 ) -> crate::err::ForensicResult<String> {
394 Ok(format!("123"))
395 }
396
397 fn value_at(
398 &self,
399 _hkey: crate::traits::registry::RegHiveKey,
400 _pos: u32,
401 ) -> crate::err::ForensicResult<String> {
402 Ok(format!("123"))
403 }
404 fn key_info(&self, _hkey: crate::traits::registry::RegHiveKey) -> ForensicResult<crate::traits::registry::RegistryKeyInfo>{
405 Ok(RegistryKeyInfo::default())
406 }
407 }
408
409 let reader = RegReader {};
410 let mut reader : Box<dyn RegistryReader> = Box::new(reader);
411 fn tst(reg : &mut Box<dyn RegistryReader>) -> ForensicResult<()>{
412 assert_eq!("123",reg.key_at(crate::traits::registry::RegHiveKey::HkeyClassesRoot, 123)?);
413 Ok(())
414 }
415 tst(&mut reader).unwrap();
416 }
417}