libprefetch/
lib.rs

1//             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyright (C) 2018 Thomas Bailleux <thomas@bailleux.me>
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14//
15// Author: zadig <thomas chr(0x40) bailleux.me>
16
17//! A forensic library which parses and reads Microsoft Prefetch files.
18//!
19//! `libprefetch` fully supports the following versions of Windows:
20//!   * Windows 2003
21//!   * Windows XP
22//!   * Windows Vista
23//!   * Windows 7
24//!   * Windows 8/8.1
25//!
26//! `libprefetch` **partially supports** Windows 10.
27//!
28//! Features:
29//!   * Parser and validator
30//!   * Auto detects version of Windows
31//!   * Provides the last execution time and the execution counter
32//!   * Provides metric information about loaded files (like dll etc) **if available**, such as :
33//!     * filename
34//!     * start time
35//!     * duration
36//!     * average duration
37//!     * NTFS MFT entry
38//!     * NTFS sequence numer
39//!   * Provides the trace chains (**unavailable for Windows 10**)
40//!   * Provides all pieces of information about the volumes:
41//!     * device path
42//!     * creation time
43//!     * serial number
44//!     * list of directories
45//!
46//! This library will be used in a global forensic computing library very soon.
47//!
48//! ## Example
49//!
50//! ```rust
51//! use libprefetch::Prefetch;
52//!
53//! let file = std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();
54//!
55//! let prefetch = Prefetch::new(file).unwrap();
56//!
57//! // Prints some information
58//! println!("Executable {} launched {} times. The last time was: {}",
59//!   prefetch.name(),
60//!   prefetch.execution_counter(),
61//!   prefetch.last_execution_time() // TODO: format the FILETIME here
62//! );
63//!
64//! // Iterates over all loaded DLL etc for the prefetch file
65//! println!(" ===== File metrics ===== ");
66//! for metric in prefetch.metrics().unwrap() {
67//!   println!("#{}: {}", metric.id(), metric.filename());
68//!   println!("    start time: {}", metric.start_time().unwrap());
69//!   println!("    duration: {}", metric.duration().unwrap());
70//!   println!(" ------------------------------- ");
71//! }
72//!
73//! // Iterates over the volumes
74//! println!(" ===== Volumes ===== ");
75//! for volume in prefetch.volumes().unwrap() {
76//!   println!("Volume #{}:", volume.id());
77//!   println!("    Path: {}", volume.device_path());
78//!   println!("    Creation time: {}", volume.creation_time());
79//!   println!("    Serial number: {}", volume.serial_number());
80//!   println!("    Directories: ");
81//!   for directory in volume.directories().unwrap() {
82//!     println!("        {}", directory);
83//!   }
84//! }
85//!
86//!
87//! ```
88//!
89//! ## Releases
90//!
91//! Release notes are available in [RELEASES.md](RELEASES.md).
92//!
93//! ## Compatibility
94//!
95//! `libprefetch` seems to work for rust 1.9 and greater.
96mod prefetch;
97mod parser;
98mod error;
99mod constants;
100mod header;
101mod util;
102pub mod iterator;
103pub mod metric;
104pub mod trace;
105pub mod volume;
106
107pub(crate) use error::Result;
108pub use prefetch::{FormatVersion, Prefetch};
109pub use error::Error;
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    fn prelude() -> prefetch::Prefetch {
116      let f =
117        std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();
118      let p = prefetch::Prefetch::new(f).unwrap();
119
120      p
121    }
122
123    #[test]
124    fn header() {
125      let p = prelude();
126      assert_eq!(129453035816965472, p.last_execution_time());
127      assert_eq!(38, p.execution_counter());
128    }
129
130    #[test]
131    fn metrics() {
132      let p = prelude();
133      for metric in p.metrics().unwrap() {
134        println!("metric={:?}", metric);
135      }
136    }
137
138    #[test]
139    fn trace() {
140      let p = prelude();
141      for trace in p.trace().unwrap() {
142        println!("trace={:?}", trace);
143      }
144    }
145
146    #[test]
147    fn volumes() {
148      let p = prelude();
149      for volume in p.volumes().unwrap() {
150        println!("volume={:?}", volume);
151      }
152    }
153
154    #[test]
155    fn volumes_directories() {
156      let p = prelude();
157      for volume in p.volumes().unwrap() {
158        for d in volume.directories().unwrap() {
159          println!("directories={:?}", d);
160        }
161      }
162    }
163
164    #[test]
165    fn readme() {
166      let file = std::fs::File::open("assets/WUAUCLT.EXE-399A8E72.pf").unwrap();
167
168      let prefetch = Prefetch::new(file).unwrap();
169
170      // Prints some information
171      println!("Executable {} launched {} times. The last time was: {}",
172        prefetch.name(),
173        prefetch.execution_counter(),
174        prefetch.last_execution_time() // TODO: format the MSTIME here
175      );
176
177      // Iterates over all loaded DLL etc for the prefetch file
178      println!(" ===== File metrics ===== ");
179      for metric in prefetch.metrics().unwrap() {
180        println!("#{}: {}", metric.id(), metric.filename());
181        println!("    start time: {}", metric.start_time().unwrap());
182        println!("    duration: {}", metric.duration().unwrap());
183        println!(" ------------------------------- ");
184      }
185
186      // Iterates over the volumes
187      println!(" ===== Volumes ===== ");
188      for volume in prefetch.volumes().unwrap() {
189        println!("Volume #{}:", volume.id());
190        println!("    Path: {}", volume.device_path());
191        println!("    Creation time: {}", volume.creation_time());
192        println!("    Serial number: {}", volume.serial_number());
193        println!("    Directories: ");
194        for directory in volume.directories().unwrap() {
195          println!("        {}", directory);
196        }
197      }
198    }
199}