readhive/
readhive.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2019 Colin Finck <colin@reactos.org>
// SPDX-License-Identifier: GPL-2.0-or-later

use nt_hive::*;
use std::env;
use std::fs::File;
use std::io::Read;
use std::ops::Deref;
use zerocopy::*;

fn main() -> Result<(), String> {
    // Parse arguments.
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage: readhive <FILENAME>");
        return Ok(());
    }

    // Read the hive file.
    let filename = &args[1];
    let mut f = File::open(filename).map_err(|e| format!("Error opening hive file: {}", e))?;
    let mut buffer = Vec::<u8>::new();
    f.read_to_end(&mut buffer)
        .map_err(|e| format!("Error reading hive file: {}", e))?;

    // Parse the hive.
    let hive = Hive::new(buffer.as_ref()).map_err(|e| format!("Error parsing hive file: {}", e))?;

    // Print the name of the root key node.
    let root_key = hive
        .root_key_node()
        .map_err(|e| format!("Error getting root key: {}", e))?;
    println!("{}", root_key.name().unwrap().to_string_lossy());

    process_subkey(root_key, 0)?;

    Ok(())
}

fn process_subkey<H, B>(key_node: KeyNode<H, B>, level: usize) -> Result<(), String>
where
    H: Deref<Target = Hive<B>>,
    B: ByteSlice,
{
    // Print the names of subkeys of this node.
    if let Some(subkeys) = key_node.subkeys() {
        let subkeys = subkeys.map_err(|e| format!("Error getting subkeys: {}", e))?;

        for key_node in subkeys {
            let key_node = key_node.map_err(|e| format!("Error enumerating key: {}", e))?;
            let key_name = key_node
                .name()
                .map_err(|e| format!("Error getting key name: {}", e))?;

            for _i in 0..level {
                print!("  ");
            }
            println!("● {}", key_name);

            // Print the names of the values of this node.
            if let Some(value_iter) = key_node.values() {
                let value_iter =
                    value_iter.map_err(|e| format!("Error creating value iterator: {}", e))?;

                for value in value_iter {
                    let value = value.map_err(|e| format!("Error enumerating value: {}", e))?;

                    let mut value_name = value
                        .name()
                        .map_err(|e| format!("Error getting value name: {}", e))?
                        .to_string_lossy();
                    if value_name.is_empty() {
                        value_name.push_str("(Default)");
                    }

                    let value_type = value
                        .data_type()
                        .map_err(|e| format!("Error getting value type: {}", e))?;

                    // First line: Value Name, Data Type, and Data Size
                    for _i in 0..level {
                        print!("  ");
                    }
                    println!(
                        "  ○ {} - {:?} - {}",
                        value_name,
                        value_type,
                        value.data_size()
                    );

                    // Second line: The actual Value Data
                    for _i in 0..level {
                        print!("  ");
                    }
                    print!("    ");

                    match value_type {
                        KeyValueDataType::RegSZ | KeyValueDataType::RegExpandSZ => {
                            let string_data = value
                                .string_data()
                                .map_err(|e| format!("Error getting string data: {}", e))?;
                            println!("{}", string_data)
                        }
                        KeyValueDataType::RegBinary => {
                            let binary_data = value
                                .data()
                                .map_err(|e| format!("Error getting binary data: {}", e))?;
                            match binary_data {
                                KeyValueData::Small(data) => println!("{:?}", data),
                                KeyValueData::Big(_iter) => println!("BIG DATA"),
                            }
                        }
                        KeyValueDataType::RegDWord | KeyValueDataType::RegDWordBigEndian => {
                            let dword_data = value
                                .dword_data()
                                .map_err(|e| format!("Error getting DWORD data: {}", e))?;
                            println!("{}", dword_data)
                        }
                        KeyValueDataType::RegMultiSZ => {
                            let multi_string_data = value
                                .multi_string_data()
                                .map_err(|e| format!("Error getting multi string data: {}", e))?;
                            println!("{:?}", multi_string_data)
                        }
                        KeyValueDataType::RegQWord => {
                            let qword_data = value
                                .qword_data()
                                .map_err(|e| format!("Error getting QWORD data: {}", e))?;
                            println!("{}", qword_data)
                        }
                        _ => println!(),
                    }
                }
            }

            // Process subkeys.
            process_subkey(key_node, level + 1)?;
        }
    }

    Ok(())
}