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
//! # File / Data Signatures
//!
//! Creating a signature to identify a particular file or data type is composed of two parts:
//!
//! 1. Defining the signature's attributes
//! 2. Writing a parser to parse and validate potential signature matches
//!
//! ## Defining a Signature
//!
//! Signatures are defined using the `signatures::common::Signature` struct. This structure stores critical information
//! about a signature, such as the signature name, the magic bytes that are associated with the signature, and which extractor
//! to use (if any) to extract the data associated with the signature.
//!
//! ### Example
//!
//! ```ignore
//! use binwalk::extractors::foobar::foobar_extractor;
//! use binwalk::signatures::common::Signature;
//! use binwalk::signatures::foobar::foobar_parser;
//!
//! // FooBar file signature
//! let foobar_signature = Signature {
//! // A unique name for the signature, no spaces; signatures can be included/excluded from analysis based on this attribute
//! name: "foobar".to_string(),
//! // Set to true for signatures with very short magic bytes; they will only be matched at file offset 0
//! short: false,
//! // Offset from the start of the file to the "magic" bytes; only really relevant for short signatures
//! magic_offset: 0,
//! // Most signatures will want to set this to false and let the code in main.rs determine if/when to display
//! always_display: false,
//! // The magic bytes associated with this signature; there may be more than one set of magic bytes per signature
//! magic: vec![b"\xF0\x00\xBA\xA2".to_vec()],
//! // This is the parser function to call to validate magic byte matches
//! parser: foobar_parser,
//! // A short human-readable description of the signature
//! description: "FooBar file".to_string(),
//! // The extractor to use to extract this file/data type
//! extractor: Some(foobar_extractor()),
//! };
//! ```
//!
//! Internally, Binwalk keeps a list of `Signature` definitions in `magic.rs`.
//!
//! ## Signature Parsers
//!
//! Signature parsers are at the heart of each defined signature. They parse and validate magic matches to ensure accuracy and
//! determine the total size of the file data (if possible).
//!
//! Signature parsers must conform to the `signatures::common::SignatureParser` type definition.
//! They are provided two arguments: the raw file data, and an offset into the file data where the signature's magic bytes were found.
//!
//! Signature parsers must parse and validate the expected signature data, and return either a `signatures::common::SignatureResult`
//! structure on success, or a `signatures::common::SignatureError` on failure.
//!
//! ### Example
//!
//! ```ignore
//! use binwalk::extractors::foobar::extract_foobar_file;
//! use binwalk::signatures::common::{SignatureResult, SignatureError, CONFIDENCE_HIGH};
//!
//! /// This function is responsible for parsing and validating the FooBar file system data whenever the "magic bytes"
//! /// are found inside a file. It is provided access to the entire file data, and an offset into the file data where
//! /// the magic bytes were found. On success, it will return a signatures::common::SignatureResult structure.
//! ///
//! pub fn foobar_parser(file_data: &Vec<u8>, offset: usize) -> Result<SignatureResult, SignatureError> {
//! /*
//! * This will be returned if the format of the suspected FooBar file system looks correct.
//! * We will update it later with more information, but for now just define what is known
//! * (the offset where the FooBar file starts, the human-readable description, and
//! * a confidence level), and leave the remaining fields at their defaults.
//! *
//! * Note that confidence level is chosen somewhat arbitrarily, and should be one of:
//! *
//! * - CONFIDENCE_LOW (the default)
//! * - CONFIDENCE_MEDIUM
//! * - CONFIDENCE_HIGH
//! *
//! * In this case the extractor and header parser (defined elsewhere) validate CRC's, so if those pass,
//! * the confidence that this is in fact a FooBar file type is high.
//! */
//! let mut result = SignatureResult {
//! offset: offset,
//! description: "FooBar file".to_string(),
//! confidence: CONFIDENCE_HIGH,
//! ..Default::default()
//! };
//!
//! /*
//! * The internal FooBar file extractor already parses the header and validates the data CRC. By passing it an output
//! * directory of None, it will still parse and validate the data, but without performing an extraction.
//! */
//! let dry_run = extact_foobar_file(file_data, offset, None);
//!
//! // The extractor should have reported success, as well as the total size of the file data
//! if dry_run.success == true {
//! if let Some(file_size) = dry_run.size {
//! // Update the reported size and human-readable description and return the result
//! result.size = file_size;
//! result.description = format!("{}, total size: {} bytes", result.description, result.size);
//! return Ok(result);
//! }
//! }
//!
//! // Something didn't look right about this file data, it is likely a false positive, so return an error
//! return Err(SignatureError);
//! }
//! ```