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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
//                    Version 2, December 2004
//
// Copyright (C) 2018 Thomas Bailleux <thomas@bailleux.me>
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
//  0. You just DO WHAT THE FUCK YOU WANT TO.
//
// Author: zadig <thomas chr(0x40) bailleux.me>

//! A forensic library which parses and reads Microsoft Prefetch files.
//!
//! `libprefetch` fully supports the following versions of Windows:
//!   * Windows 2003
//!   * Windows XP
//!   * Windows Vista
//!   * Windows 7
//!   * Windows 8/8.1
//!
//! `libprefetch` **partially supports** Windows 10.
//!
//! Features:
//!   * Parser and validator
//!   * Auto detects version of Windows
//!   * Provides the last execution time and the execution counter
//!   * Provides metric information about loaded files (like dll etc) **if available**, such as :
//!     * filename
//!     * start time
//!     * duration
//!     * average duration
//!     * NTFS MFT entry
//!     * NTFS sequence numer
//!   * Provides the trace chains (**unavailable for Windows 10**)
//!   * Provides all pieces of information about the volumes:
//!     * device path
//!     * creation time
//!     * serial number
//!     * list of directories
//!
//! This library will be used in a global forensic computing library very soon.
//!
//! ## Example
//!
//! ```rust
//! use libprefetch::Prefetch;
//!
//! let file = std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();
//!
//! let prefetch = Prefetch::new(file).unwrap();
//!
//! // Prints some information
//! println!("Executable {} launched {} times. The last time was: {}",
//!   prefetch.name(),
//!   prefetch.execution_counter(),
//!   prefetch.last_execution_time() // TODO: format the FILETIME here
//! );
//!
//! // Iterates over all loaded DLL etc for the prefetch file
//! println!(" ===== File metrics ===== ");
//! for metric in prefetch.metrics().unwrap() {
//!   println!("#{}: {}", metric.id(), metric.filename());
//!   println!("    start time: {}", metric.start_time().unwrap());
//!   println!("    duration: {}", metric.duration().unwrap());
//!   println!(" ------------------------------- ");
//! }
//!
//! // Iterates over the volumes
//! println!(" ===== Volumes ===== ");
//! for volume in prefetch.volumes().unwrap() {
//!   println!("Volume #{}:", volume.id());
//!   println!("    Path: {}", volume.device_path());
//!   println!("    Creation time: {}", volume.creation_time());
//!   println!("    Serial number: {}", volume.serial_number());
//!   println!("    Directories: ");
//!   for directory in volume.directories().unwrap() {
//!     println!("        {}", directory);
//!   }
//! }
//!
//!
//! ```
//!
//! ## Releases
//!
//! Release notes are available in [RELEASES.md](RELEASES.md).
//!
//! ## Compatibility
//!
//! `libprefetch` seems to work for rust 1.9 and greater.
mod prefetch;
mod parser;
mod error;
mod constants;
mod header;
mod util;
pub mod iterator;
pub mod metric;
pub mod trace;
pub mod volume;

pub(crate) use error::Result;
pub use prefetch::{FormatVersion, Prefetch};
pub use error::Error;

#[cfg(test)]
mod tests {
    use super::*;

    fn prelude() -> prefetch::Prefetch {
      let f =
        std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();
      let p = prefetch::Prefetch::new(f).unwrap();

      p
    }

    #[test]
    fn header() {
      let p = prelude();
      assert_eq!(129453035816965472, p.last_execution_time());
      assert_eq!(38, p.execution_counter());
    }

    #[test]
    fn metrics() {
      let p = prelude();
      for metric in p.metrics().unwrap() {
        println!("metric={:?}", metric);
      }
    }

    #[test]
    fn trace() {
      let p = prelude();
      for trace in p.trace().unwrap() {
        println!("trace={:?}", trace);
      }
    }

    #[test]
    fn volumes() {
      let p = prelude();
      for volume in p.volumes().unwrap() {
        println!("volume={:?}", volume);
      }
    }

    #[test]
    fn volumes_directories() {
      let p = prelude();
      for volume in p.volumes().unwrap() {
        for d in volume.directories().unwrap() {
          println!("directories={:?}", d);
        }
      }
    }

    #[test]
    fn readme() {
      let file = std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();

      let prefetch = Prefetch::new(file).unwrap();

      // Prints some information
      println!("Executable {} launched {} times. The last time was: {}",
        prefetch.name(),
        prefetch.execution_counter(),
        prefetch.last_execution_time() // TODO: format the MSTIME here
      );

      // Iterates over all loaded DLL etc for the prefetch file
      println!(" ===== File metrics ===== ");
      for metric in prefetch.metrics().unwrap() {
        println!("#{}: {}", metric.id(), metric.filename());
        println!("    start time: {}", metric.start_time().unwrap());
        println!("    duration: {}", metric.duration().unwrap());
        println!(" ------------------------------- ");
      }

      // Iterates over the volumes
      println!(" ===== Volumes ===== ");
      for volume in prefetch.volumes().unwrap() {
        println!("Volume #{}:", volume.id());
        println!("    Path: {}", volume.device_path());
        println!("    Creation time: {}", volume.creation_time());
        println!("    Serial number: {}", volume.serial_number());
        println!("    Directories: ");
        for directory in volume.directories().unwrap() {
          println!("        {}", directory);
        }
      }
    }
}