Welcome to mirror list, hosted at ThFree Co, Russian Federation.

main.rs « src - github.com/windirstat/RustyMft.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 59f1d508462789291d02b9c4dc3a15e43cfa208c (plain)
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
#[macro_use] extern crate log;
extern crate rustymft;
extern crate rwinstructs;
extern crate serde_json;
extern crate jmespath;
extern crate serde;
extern crate clap;
use clap::{App, Arg, ArgMatches};
use rustymft::mft::{MftHandler};
use jmespath::{Expression};
use rwinstructs::reference;
use rwinstructs::serialize;
use serde::Serializer;
use serde::ser::SerializeSeq;
use std::fs;
use std::io;

fn process_directory(directory: &str, options: ArgMatches) {
    for entry in fs::read_dir(directory).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if path.is_file() {
            let path_string = path.into_os_string().into_string().unwrap();
            if path_string.ends_with("mft"){
                process_file(&path_string,options.clone());
            }
        }
    }
}

fn process_file(filename: &str,options: ArgMatches) -> bool {
    // JMES Expression if needed
    let mut expr: Option<Expression> = None;
    if options.is_present("query") {
        expr = Some(jmespath::compile(
            options.value_of("query").unwrap()
        ).unwrap());
    }

    // Expression bool flag
    let mut expr_as_bool = false;
    if options.is_present("bool_expr"){
        expr_as_bool = true;
    }

    let mut mft_handler = match MftHandler::new(filename) {
        Ok(mft_handler) => mft_handler,
        Err(error) => {
            warn!("Could not parse file: {} [error: {}]", filename, error);
            return false;
        }
    };

    for i in 0 .. mft_handler.get_entry_count() {
        let mft_entry = match mft_handler.entry(i) {
            Ok(mft_entry) => {
                let json_str = serde_json::to_string(&mft_entry).unwrap();

                match expr {
                    Some(ref j_expr) => {
                        let data = jmespath::Variable::from_json(&json_str).unwrap();
                        let result = j_expr.search(data).unwrap();
                        if expr_as_bool {
                            match result.as_boolean() {
                                Some(bool_value) => {
                                    match bool_value {
                                        true => println!("{}",json_str),
                                        false => {}
                                    }
                                },
                                None => {
                                    panic!("Query expression is not a bool expression!");
                                }
                            }
                        } else {
                            println!("{}",result)
                        }
                    },
                    None => {
                        println!("{}",json_str);
                    }
                }
            },
            Err(error) => {
                warn!("Could not parse file: {} [error: {}]", filename, error);
                continue;
            }
        };
    }

    return true;
}

fn is_directory(source: &str)->bool{
    fs::metadata(source).unwrap().file_type().is_dir()
}

fn main() {
    let source_arg = Arg::with_name("source")
        .short("s")
        .long("source")
        .value_name("FILE")
        .help("The source path. Can be a file or a directory.")
        .required(true)
        .takes_value(true);

    let jmes_arg = Arg::with_name("query")
        .short("q")
        .long("query")
        .value_name("QUERY")
        .help("JMES Query")
        .takes_value(true);

    let bool_arg = Arg::with_name("bool_expr")
        .short("b")
        .long("bool_expr")
        .help("JMES Query as bool only. (Prints whole record if true.)");

    let options = App::new("RustyMft")
        .version("0.1.0")
        .author("Matthew Seyer <https://github.com/forensicmatt/RustyMft>")
        .about("Parse $MFT.")
        .arg(source_arg)
        .arg(jmes_arg)
        .arg(bool_arg)
        .get_matches();

    // Set Reference Display Options
    unsafe{reference::NESTED_REFERENCE = true;}
    unsafe{serialize::U64_SERIALIZATION = serialize::U64Serialization::AsString;}

    let source = options.value_of("source").unwrap();

    if is_directory(source) {
        panic!("Directory source is not implemented yet.");
    } else {
        process_file(source,options.clone());
    }
}