/src/libbde/libbde/libbde_volume_header.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The BDE volume header functions |
3 | | * |
4 | | * Copyright (C) 2011-2024, Joachim Metz <joachim.metz@gmail.com> |
5 | | * |
6 | | * Refer to AUTHORS for acknowledgements. |
7 | | * |
8 | | * This program is free software: you can redistribute it and/or modify |
9 | | * it under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation, either version 3 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <common.h> |
23 | | #include <byte_stream.h> |
24 | | #include <memory.h> |
25 | | #include <types.h> |
26 | | |
27 | | #include "libbde_debug.h" |
28 | | #include "libbde_definitions.h" |
29 | | #include "libbde_libbfio.h" |
30 | | #include "libbde_libcerror.h" |
31 | | #include "libbde_libcnotify.h" |
32 | | #include "libbde_libfguid.h" |
33 | | #include "libbde_volume_header.h" |
34 | | |
35 | | #include "bde_volume.h" |
36 | | |
37 | | const uint8_t bde_boot_entry_point_vista[ 3 ] = { |
38 | | 0xeb, 0x52, 0x90 }; |
39 | | |
40 | | const uint8_t bde_boot_entry_point_windows7[ 3 ] = { |
41 | | 0xeb, 0x58, 0x90 }; |
42 | | |
43 | | const uint8_t bde_identifier[ 16 ] = { |
44 | | 0x3b, 0xd6, 0x67, 0x49, 0x29, 0x2e, 0xd8, 0x4a, 0x83, 0x99, 0xf6, 0xa3, 0x39, 0xe3, 0xd0, 0x01 }; |
45 | | |
46 | | const uint8_t bde_identifier_used_disk_space_only[ 16 ] = { |
47 | | 0x3b, 0x4d, 0xa8, 0x92, 0x80, 0xdd, 0x0e, 0x4d, 0x9e, 0x4e, 0xb1, 0xe3, 0x28, 0x4e, 0xae, 0xd8 }; |
48 | | |
49 | | const char *bde_signature = "-FVE-FS-"; |
50 | | |
51 | | /* Creates a volume header |
52 | | * Make sure the value volume_header is referencing, is set to NULL |
53 | | * Returns 1 if successful or -1 on error |
54 | | */ |
55 | | int libbde_volume_header_initialize( |
56 | | libbde_volume_header_t **volume_header, |
57 | | libcerror_error_t **error ) |
58 | 2.43k | { |
59 | 2.43k | static char *function = "libbde_volume_header_initialize"; |
60 | | |
61 | 2.43k | if( volume_header == NULL ) |
62 | 0 | { |
63 | 0 | libcerror_error_set( |
64 | 0 | error, |
65 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
66 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
67 | 0 | "%s: invalid volume header.", |
68 | 0 | function ); |
69 | |
|
70 | 0 | return( -1 ); |
71 | 0 | } |
72 | 2.43k | if( *volume_header != NULL ) |
73 | 0 | { |
74 | 0 | libcerror_error_set( |
75 | 0 | error, |
76 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
77 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
78 | 0 | "%s: invalid volume header value already set.", |
79 | 0 | function ); |
80 | |
|
81 | 0 | return( -1 ); |
82 | 0 | } |
83 | 2.43k | *volume_header = memory_allocate_structure( |
84 | 2.43k | libbde_volume_header_t ); |
85 | | |
86 | 2.43k | if( *volume_header == NULL ) |
87 | 0 | { |
88 | 0 | libcerror_error_set( |
89 | 0 | error, |
90 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
91 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
92 | 0 | "%s: unable to create volume header.", |
93 | 0 | function ); |
94 | |
|
95 | 0 | goto on_error; |
96 | 0 | } |
97 | 2.43k | if( memory_set( |
98 | 2.43k | *volume_header, |
99 | 2.43k | 0, |
100 | 2.43k | sizeof( libbde_volume_header_t ) ) == NULL ) |
101 | 0 | { |
102 | 0 | libcerror_error_set( |
103 | 0 | error, |
104 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
105 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
106 | 0 | "%s: unable to clear volume header.", |
107 | 0 | function ); |
108 | |
|
109 | 0 | goto on_error; |
110 | 0 | } |
111 | 2.43k | return( 1 ); |
112 | | |
113 | 0 | on_error: |
114 | 0 | if( *volume_header != NULL ) |
115 | 0 | { |
116 | 0 | memory_free( |
117 | 0 | *volume_header ); |
118 | |
|
119 | 0 | *volume_header = NULL; |
120 | 0 | } |
121 | 0 | return( -1 ); |
122 | 2.43k | } |
123 | | |
124 | | /* Frees a volume header |
125 | | * Returns 1 if successful or -1 on error |
126 | | */ |
127 | | int libbde_volume_header_free( |
128 | | libbde_volume_header_t **volume_header, |
129 | | libcerror_error_t **error ) |
130 | 2.43k | { |
131 | 2.43k | static char *function = "libbde_volume_header_free"; |
132 | | |
133 | 2.43k | if( volume_header == NULL ) |
134 | 0 | { |
135 | 0 | libcerror_error_set( |
136 | 0 | error, |
137 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
138 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
139 | 0 | "%s: invalid volume header.", |
140 | 0 | function ); |
141 | |
|
142 | 0 | return( -1 ); |
143 | 0 | } |
144 | 2.43k | if( *volume_header != NULL ) |
145 | 2.43k | { |
146 | 2.43k | memory_free( |
147 | 2.43k | *volume_header ); |
148 | | |
149 | 2.43k | *volume_header = NULL; |
150 | 2.43k | } |
151 | 2.43k | return( 1 ); |
152 | 2.43k | } |
153 | | |
154 | | /* Reads the volume header |
155 | | * Returns 1 if successful or -1 on error |
156 | | */ |
157 | | int libbde_volume_header_read_data( |
158 | | libbde_volume_header_t *volume_header, |
159 | | const uint8_t *data, |
160 | | size_t data_size, |
161 | | libcerror_error_t **error ) |
162 | 2.41k | { |
163 | 2.41k | static char *function = "libbde_volume_header_read_data"; |
164 | 2.41k | uint64_t safe_first_metadata_offset = 0; |
165 | 2.41k | uint64_t safe_second_metadata_offset = 0; |
166 | 2.41k | uint64_t safe_third_metadata_offset = 0; |
167 | 2.41k | uint64_t total_number_of_sectors = 0; |
168 | 2.41k | uint32_t cluster_block_size = 0; |
169 | | |
170 | | #if defined( HAVE_DEBUG_OUTPUT ) |
171 | | uint64_t value_64bit = 0; |
172 | | uint32_t value_32bit = 0; |
173 | | uint16_t value_16bit = 0; |
174 | | #endif |
175 | | |
176 | 2.41k | if( volume_header == NULL ) |
177 | 0 | { |
178 | 0 | libcerror_error_set( |
179 | 0 | error, |
180 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
181 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
182 | 0 | "%s: invalid volume header.", |
183 | 0 | function ); |
184 | |
|
185 | 0 | return( -1 ); |
186 | 0 | } |
187 | 2.41k | if( data == NULL ) |
188 | 0 | { |
189 | 0 | libcerror_error_set( |
190 | 0 | error, |
191 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
192 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
193 | 0 | "%s: invalid data.", |
194 | 0 | function ); |
195 | |
|
196 | 0 | return( -1 ); |
197 | 0 | } |
198 | 2.41k | if( ( data_size < 512 ) |
199 | 2.41k | || ( data_size > (size_t) SSIZE_MAX ) ) |
200 | 0 | { |
201 | 0 | libcerror_error_set( |
202 | 0 | error, |
203 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
204 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
205 | 0 | "%s: invalid data size value out of bounds.", |
206 | 0 | function ); |
207 | |
|
208 | 0 | return( -1 ); |
209 | 0 | } |
210 | | #if defined( HAVE_DEBUG_OUTPUT ) |
211 | | if( libcnotify_verbose != 0 ) |
212 | | { |
213 | | libcnotify_printf( |
214 | | "%s: volume header data:\n", |
215 | | function ); |
216 | | libcnotify_print_data( |
217 | | data, |
218 | | 512, |
219 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
220 | | } |
221 | | #endif |
222 | 2.41k | if( memory_compare( |
223 | 2.41k | data, |
224 | 2.41k | bde_boot_entry_point_vista, |
225 | 2.41k | 3 ) == 0 ) |
226 | 243 | { |
227 | 243 | volume_header->version = LIBBDE_VERSION_WINDOWS_VISTA; |
228 | 243 | } |
229 | 2.17k | else if( memory_compare( |
230 | 2.17k | data, |
231 | 2.17k | bde_boot_entry_point_windows7, |
232 | 2.17k | 3 ) == 0 ) |
233 | 2.12k | { |
234 | 2.12k | if( memory_compare( |
235 | 2.12k | ( (bde_volume_header_windows_7_t *) data )->identifier, |
236 | 2.12k | bde_identifier, |
237 | 2.12k | 16 ) == 0 ) |
238 | 1.34k | { |
239 | 1.34k | volume_header->version = LIBBDE_VERSION_WINDOWS_7; |
240 | 1.34k | } |
241 | | #if defined( HAVE_DEBUG_OUTPUT ) |
242 | | else if( memory_compare( |
243 | | ( (bde_volume_header_windows_7_t *) data )->identifier, |
244 | | bde_identifier_used_disk_space_only, |
245 | | 16 ) == 0 ) |
246 | | { |
247 | | volume_header->version = LIBBDE_VERSION_WINDOWS_7; |
248 | | } |
249 | | #endif |
250 | 778 | else if( memory_compare( |
251 | 778 | ( (bde_volume_header_to_go_t *) data )->identifier, |
252 | 778 | bde_identifier, |
253 | 778 | 16 ) == 0 ) |
254 | 718 | { |
255 | 718 | volume_header->version = LIBBDE_VERSION_TO_GO; |
256 | 718 | } |
257 | 60 | else |
258 | 60 | { |
259 | 60 | libcerror_error_set( |
260 | 60 | error, |
261 | 60 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
262 | 60 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
263 | 60 | "%s: unsupported identifier.", |
264 | 60 | function ); |
265 | | |
266 | 60 | return( -1 ); |
267 | 60 | } |
268 | 2.12k | } |
269 | 52 | else |
270 | 52 | { |
271 | 52 | libcerror_error_set( |
272 | 52 | error, |
273 | 52 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
274 | 52 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
275 | 52 | "%s: unsupported volume boot entry point.", |
276 | 52 | function ); |
277 | | |
278 | 52 | return( -1 ); |
279 | 52 | } |
280 | 2.30k | if( ( volume_header->version == LIBBDE_VERSION_WINDOWS_VISTA ) |
281 | 2.30k | || ( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) ) |
282 | 1.58k | { |
283 | 1.58k | if( memory_compare( |
284 | 1.58k | &( data[ 3 ] ), |
285 | 1.58k | bde_signature, |
286 | 1.58k | 8 ) != 0 ) |
287 | 18 | { |
288 | 18 | libcerror_error_set( |
289 | 18 | error, |
290 | 18 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
291 | 18 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
292 | 18 | "%s: invalid volume signature.", |
293 | 18 | function ); |
294 | | |
295 | 18 | return( -1 ); |
296 | 18 | } |
297 | 1.58k | } |
298 | 2.28k | byte_stream_copy_to_uint16_little_endian( |
299 | 2.28k | ( (bde_volume_header_windows_vista_t *) data )->bytes_per_sector, |
300 | 2.28k | volume_header->bytes_per_sector ); |
301 | | |
302 | 2.28k | volume_header->sectors_per_cluster_block = ( (bde_volume_header_windows_vista_t *) data )->sectors_per_cluster_block; |
303 | | |
304 | 2.28k | byte_stream_copy_to_uint16_little_endian( |
305 | 2.28k | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_16bit, |
306 | 2.28k | total_number_of_sectors ); |
307 | | |
308 | 2.28k | if( total_number_of_sectors == 0 ) |
309 | 907 | { |
310 | 907 | byte_stream_copy_to_uint32_little_endian( |
311 | 907 | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_32bit, |
312 | 907 | total_number_of_sectors ); |
313 | 907 | } |
314 | 2.28k | if( volume_header->version == LIBBDE_VERSION_WINDOWS_VISTA ) |
315 | 236 | { |
316 | 236 | byte_stream_copy_to_uint64_little_endian( |
317 | 236 | ( (bde_volume_header_windows_vista_t *) data )->first_metadata_cluster_block_number, |
318 | 236 | safe_first_metadata_offset ); |
319 | | |
320 | 236 | if( total_number_of_sectors == 0 ) |
321 | 135 | { |
322 | 135 | byte_stream_copy_to_uint64_little_endian( |
323 | 135 | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_64bit, |
324 | 135 | total_number_of_sectors ); |
325 | 135 | } |
326 | 236 | } |
327 | 2.04k | else if( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
328 | 1.33k | { |
329 | 1.33k | byte_stream_copy_to_uint64_little_endian( |
330 | 1.33k | ( (bde_volume_header_windows_7_t *) data )->first_metadata_offset, |
331 | 1.33k | safe_first_metadata_offset ); |
332 | | |
333 | 1.33k | byte_stream_copy_to_uint64_little_endian( |
334 | 1.33k | ( (bde_volume_header_windows_7_t *) data )->second_metadata_offset, |
335 | 1.33k | safe_second_metadata_offset ); |
336 | | |
337 | 1.33k | byte_stream_copy_to_uint64_little_endian( |
338 | 1.33k | ( (bde_volume_header_windows_7_t *) data )->third_metadata_offset, |
339 | 1.33k | safe_third_metadata_offset ); |
340 | 1.33k | } |
341 | 718 | else if( volume_header->version == LIBBDE_VERSION_TO_GO ) |
342 | 718 | { |
343 | 718 | byte_stream_copy_to_uint64_little_endian( |
344 | 718 | ( (bde_volume_header_to_go_t *) data )->first_metadata_offset, |
345 | 718 | safe_first_metadata_offset ); |
346 | | |
347 | 718 | byte_stream_copy_to_uint64_little_endian( |
348 | 718 | ( (bde_volume_header_to_go_t *) data )->second_metadata_offset, |
349 | 718 | safe_second_metadata_offset ); |
350 | | |
351 | 718 | byte_stream_copy_to_uint64_little_endian( |
352 | 718 | ( (bde_volume_header_to_go_t *) data )->third_metadata_offset, |
353 | 718 | safe_third_metadata_offset ); |
354 | 718 | } |
355 | | #if defined( HAVE_DEBUG_OUTPUT ) |
356 | | if( libcnotify_verbose != 0 ) |
357 | | { |
358 | | libcnotify_printf( |
359 | | "%s: boot entry point:\n", |
360 | | function ); |
361 | | libcnotify_print_data( |
362 | | data, |
363 | | 3, |
364 | | 0 ); |
365 | | |
366 | | libcnotify_printf( |
367 | | "%s: signature\t\t\t\t: %c%c%c%c%c%c%c%c\n", |
368 | | function, |
369 | | data[ 3 ], |
370 | | data[ 4 ], |
371 | | data[ 5 ], |
372 | | data[ 6 ], |
373 | | data[ 7 ], |
374 | | data[ 8 ], |
375 | | data[ 9 ], |
376 | | data[ 10 ] ); |
377 | | |
378 | | libcnotify_printf( |
379 | | "%s: bytes per sector\t\t\t: %" PRIu16 "\n", |
380 | | function, |
381 | | volume_header->bytes_per_sector ); |
382 | | |
383 | | libcnotify_printf( |
384 | | "%s: sectors per cluster block\t\t: %" PRIu8 "\n", |
385 | | function, |
386 | | volume_header->sectors_per_cluster_block ); |
387 | | |
388 | | libcnotify_printf( |
389 | | "%s: unknown1\n", |
390 | | function ); |
391 | | libcnotify_print_data( |
392 | | ( (bde_volume_header_windows_vista_t *) data )->unknown1, |
393 | | 5, |
394 | | 0 ); |
395 | | |
396 | | byte_stream_copy_to_uint16_little_endian( |
397 | | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_16bit, |
398 | | value_16bit ); |
399 | | libcnotify_printf( |
400 | | "%s: total number of sectors (16-bit)\t: %" PRIu16 "\n", |
401 | | function, |
402 | | value_16bit ); |
403 | | |
404 | | libcnotify_printf( |
405 | | "%s: media descriptor\t\t\t: 0x%02" PRIx8 "\n", |
406 | | function, |
407 | | ( (bde_volume_header_windows_vista_t *) data )->media_descriptor ); |
408 | | |
409 | | byte_stream_copy_to_uint16_little_endian( |
410 | | ( (bde_volume_header_windows_vista_t *) data )->unknown2, |
411 | | value_16bit ); |
412 | | libcnotify_printf( |
413 | | "%s: unknown2\t\t\t\t: %" PRIu16 "\n", |
414 | | function, |
415 | | value_16bit ); |
416 | | |
417 | | byte_stream_copy_to_uint16_little_endian( |
418 | | ( (bde_volume_header_windows_vista_t *) data )->sectors_per_track, |
419 | | value_16bit ); |
420 | | libcnotify_printf( |
421 | | "%s: sectors per track\t\t\t: %" PRIu16 "\n", |
422 | | function, |
423 | | value_16bit ); |
424 | | |
425 | | byte_stream_copy_to_uint16_little_endian( |
426 | | ( (bde_volume_header_windows_vista_t *) data )->number_of_heads, |
427 | | value_16bit ); |
428 | | libcnotify_printf( |
429 | | "%s: number of heads\t\t\t\t: %" PRIu16 "\n", |
430 | | function, |
431 | | value_16bit ); |
432 | | |
433 | | byte_stream_copy_to_uint32_little_endian( |
434 | | ( (bde_volume_header_windows_vista_t *) data )->number_of_hidden_sectors, |
435 | | value_32bit ); |
436 | | libcnotify_printf( |
437 | | "%s: number of hidden sectors\t\t: %" PRIu32 "\n", |
438 | | function, |
439 | | value_32bit ); |
440 | | |
441 | | byte_stream_copy_to_uint32_little_endian( |
442 | | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_32bit, |
443 | | value_32bit ); |
444 | | libcnotify_printf( |
445 | | "%s: total number of sectors (32-bit)\t: %" PRIu32 "\n", |
446 | | function, |
447 | | value_32bit ); |
448 | | |
449 | | if( volume_header->version == LIBBDE_VERSION_WINDOWS_VISTA ) |
450 | | { |
451 | | byte_stream_copy_to_uint32_little_endian( |
452 | | ( (bde_volume_header_windows_vista_t *) data )->unknown4, |
453 | | value_32bit ); |
454 | | libcnotify_printf( |
455 | | "%s: unknown4\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", |
456 | | function, |
457 | | value_32bit, |
458 | | value_32bit ); |
459 | | |
460 | | byte_stream_copy_to_uint32_little_endian( |
461 | | ( (bde_volume_header_windows_vista_t *) data )->total_number_of_sectors_64bit, |
462 | | value_64bit ); |
463 | | libcnotify_printf( |
464 | | "%s: total number of sectors (64-bit)\t: %" PRIu64 "\n", |
465 | | function, |
466 | | value_64bit ); |
467 | | |
468 | | byte_stream_copy_to_uint64_little_endian( |
469 | | ( (bde_volume_header_windows_vista_t *) data )->mft_cluster_block_number, |
470 | | value_64bit ); |
471 | | libcnotify_printf( |
472 | | "%s: MFT cluster block number\t\t: %" PRIu64 "\n", |
473 | | function, |
474 | | value_64bit ); |
475 | | |
476 | | libcnotify_printf( |
477 | | "%s: first metadata cluster block\t: 0x%08" PRIx64 "\n", |
478 | | function, |
479 | | safe_first_metadata_offset ); |
480 | | |
481 | | byte_stream_copy_to_uint32_little_endian( |
482 | | ( (bde_volume_header_windows_vista_t *) data )->mft_entry_size, |
483 | | value_32bit ); |
484 | | libcnotify_printf( |
485 | | "%s: MFT entry size\t\t\t: %" PRIu32 "\n", |
486 | | function, |
487 | | value_32bit ); |
488 | | |
489 | | byte_stream_copy_to_uint32_little_endian( |
490 | | ( (bde_volume_header_windows_vista_t *) data )->index_entry_size, |
491 | | value_32bit ); |
492 | | libcnotify_printf( |
493 | | "%s: index entry size\t\t\t: %" PRIu32 "\n", |
494 | | function, |
495 | | value_32bit ); |
496 | | |
497 | | byte_stream_copy_to_uint64_little_endian( |
498 | | ( (bde_volume_header_windows_vista_t *) data )->volume_serial_number, |
499 | | value_64bit ); |
500 | | libcnotify_printf( |
501 | | "%s: volume serial number\t\t\t: 0x%08" PRIx64 "\n", |
502 | | function, |
503 | | value_64bit ); |
504 | | |
505 | | byte_stream_copy_to_uint32_little_endian( |
506 | | ( (bde_volume_header_windows_vista_t *) data )->checksum, |
507 | | value_32bit ); |
508 | | libcnotify_printf( |
509 | | "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", |
510 | | function, |
511 | | value_32bit ); |
512 | | |
513 | | libcnotify_printf( |
514 | | "%s: bootcode\n", |
515 | | function ); |
516 | | libcnotify_print_data( |
517 | | ( (bde_volume_header_windows_vista_t *) data )->bootcode, |
518 | | 426, |
519 | | 0 ); |
520 | | } |
521 | | else if( ( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
522 | | || ( volume_header->version == LIBBDE_VERSION_TO_GO ) ) |
523 | | { |
524 | | libcnotify_printf( |
525 | | "%s: unknown4:\n", |
526 | | function ); |
527 | | libcnotify_print_data( |
528 | | ( (bde_volume_header_windows_7_t *) data )->unknown4, |
529 | | 31, |
530 | | 0 ); |
531 | | |
532 | | byte_stream_copy_to_uint32_little_endian( |
533 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 0 ] ), |
534 | | value_32bit ); |
535 | | libcnotify_printf( |
536 | | "%s: unknown4a\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", |
537 | | function, |
538 | | value_32bit, |
539 | | value_32bit ); |
540 | | |
541 | | byte_stream_copy_to_uint64_little_endian( |
542 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 4 ] ), |
543 | | value_64bit ); |
544 | | libcnotify_printf( |
545 | | "%s: unknown4b\t\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", |
546 | | function, |
547 | | value_64bit, |
548 | | value_64bit ); |
549 | | |
550 | | byte_stream_copy_to_uint16_little_endian( |
551 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 12 ] ), |
552 | | value_16bit ); |
553 | | libcnotify_printf( |
554 | | "%s: unknown4c\t\t\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", |
555 | | function, |
556 | | value_16bit, |
557 | | value_16bit ); |
558 | | |
559 | | byte_stream_copy_to_uint16_little_endian( |
560 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 14 ] ), |
561 | | value_16bit ); |
562 | | libcnotify_printf( |
563 | | "%s: unknown4d\t\t\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", |
564 | | function, |
565 | | value_16bit, |
566 | | value_16bit ); |
567 | | |
568 | | byte_stream_copy_to_uint64_little_endian( |
569 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 16 ] ), |
570 | | value_64bit ); |
571 | | libcnotify_printf( |
572 | | "%s: unknown4e\t\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", |
573 | | function, |
574 | | value_64bit, |
575 | | value_64bit ); |
576 | | |
577 | | byte_stream_copy_to_uint32_little_endian( |
578 | | &( ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 24 ] ), |
579 | | value_32bit ); |
580 | | libcnotify_printf( |
581 | | "%s: unknown4f\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", |
582 | | function, |
583 | | value_32bit, |
584 | | value_32bit ); |
585 | | |
586 | | libcnotify_printf( |
587 | | "%s: drive physical number\t\t\t: 0x%02" PRIx8 "\n", |
588 | | function, |
589 | | ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 28 ] ); |
590 | | |
591 | | libcnotify_printf( |
592 | | "%s: unknown4g\t\t\t\t: 0x%02" PRIx8 "\n", |
593 | | function, |
594 | | ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 29 ] ); |
595 | | |
596 | | libcnotify_printf( |
597 | | "%s: extended boot signature\t\t\t: 0x%02" PRIx8 "\n", |
598 | | function, |
599 | | ( ( (bde_volume_header_windows_7_t *) data )->unknown4 )[ 30 ] ); |
600 | | |
601 | | libcnotify_printf( |
602 | | "\n" ); |
603 | | |
604 | | byte_stream_copy_to_uint32_little_endian( |
605 | | ( (bde_volume_header_windows_7_t *) data )->volume_serial_number, |
606 | | value_32bit ); |
607 | | libcnotify_printf( |
608 | | "%s: volume serial number\t\t\t: 0x%08" PRIx32 "\n", |
609 | | function, |
610 | | value_32bit ); |
611 | | |
612 | | libcnotify_printf( |
613 | | "%s: volume label\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c\n", |
614 | | function, |
615 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 0 ], |
616 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 1 ], |
617 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 2 ], |
618 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 3 ], |
619 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 4 ], |
620 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 5 ], |
621 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 6 ], |
622 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 7 ], |
623 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 8 ], |
624 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 9 ], |
625 | | ( (bde_volume_header_windows_7_t *) data )->volume_label[ 10 ] ); |
626 | | |
627 | | libcnotify_printf( |
628 | | "%s: file system signature\t\t\t: %c%c%c%c%c%c%c%c\n", |
629 | | function, |
630 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 0 ], |
631 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 1 ], |
632 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 2 ], |
633 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 3 ], |
634 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 4 ], |
635 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 5 ], |
636 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 6 ], |
637 | | ( (bde_volume_header_windows_7_t *) data )->file_system_signature[ 7 ] ); |
638 | | } |
639 | | if( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
640 | | { |
641 | | libcnotify_printf( |
642 | | "%s: bootcode\n", |
643 | | function ); |
644 | | libcnotify_print_data( |
645 | | ( (bde_volume_header_windows_7_t *) data )->bootcode, |
646 | | 47, |
647 | | 0 ); |
648 | | |
649 | | if( libbde_debug_print_guid_value( |
650 | | function, |
651 | | "identifier\t\t\t\t", |
652 | | ( (bde_volume_header_windows_7_t *) data )->identifier, |
653 | | 16, |
654 | | LIBFGUID_ENDIAN_LITTLE, |
655 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
656 | | error ) != 1 ) |
657 | | { |
658 | | libcerror_error_set( |
659 | | error, |
660 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
661 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
662 | | "%s: unable to print GUID value.", |
663 | | function ); |
664 | | |
665 | | return( -1 ); |
666 | | } |
667 | | } |
668 | | else if( volume_header->version == LIBBDE_VERSION_TO_GO ) |
669 | | { |
670 | | libcnotify_printf( |
671 | | "%s: bootcode\n", |
672 | | function ); |
673 | | libcnotify_print_data( |
674 | | ( (bde_volume_header_to_go_t *) data )->bootcode, |
675 | | 335, |
676 | | 0 ); |
677 | | |
678 | | if( libbde_debug_print_guid_value( |
679 | | function, |
680 | | "identifier\t\t\t\t", |
681 | | ( (bde_volume_header_to_go_t *) data )->identifier, |
682 | | 16, |
683 | | LIBFGUID_ENDIAN_LITTLE, |
684 | | LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, |
685 | | error ) != 1 ) |
686 | | { |
687 | | libcerror_error_set( |
688 | | error, |
689 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
690 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
691 | | "%s: unable to print GUID value.", |
692 | | function ); |
693 | | |
694 | | return( -1 ); |
695 | | } |
696 | | } |
697 | | if( ( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
698 | | || ( volume_header->version == LIBBDE_VERSION_TO_GO ) ) |
699 | | { |
700 | | libcnotify_printf( |
701 | | "%s: first metadata offset\t\t\t: 0x%08" PRIx64 "\n", |
702 | | function, |
703 | | safe_first_metadata_offset ); |
704 | | |
705 | | libcnotify_printf( |
706 | | "%s: second metadata offset\t\t\t: 0x%08" PRIx64 "\n", |
707 | | function, |
708 | | safe_second_metadata_offset ); |
709 | | |
710 | | libcnotify_printf( |
711 | | "%s: third metadata offset\t\t\t: 0x%08" PRIx64 "\n", |
712 | | function, |
713 | | safe_third_metadata_offset ); |
714 | | } |
715 | | if( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
716 | | { |
717 | | libcnotify_printf( |
718 | | "%s: unknown5:\n", |
719 | | function ); |
720 | | libcnotify_print_data( |
721 | | ( (bde_volume_header_windows_7_t *) data )->unknown5, |
722 | | 310, |
723 | | 0 ); |
724 | | } |
725 | | else if( volume_header->version == LIBBDE_VERSION_TO_GO ) |
726 | | { |
727 | | libcnotify_printf( |
728 | | "%s: unknown5:\n", |
729 | | function ); |
730 | | libcnotify_print_data( |
731 | | ( (bde_volume_header_to_go_t *) data )->unknown5, |
732 | | 46, |
733 | | 0 ); |
734 | | } |
735 | | byte_stream_copy_to_uint16_little_endian( |
736 | | ( (bde_volume_header_windows_vista_t *) data )->sector_signature, |
737 | | value_16bit ); |
738 | | libcnotify_printf( |
739 | | "%s: sector signature\t\t\t: 0x%04" PRIx16 "\n", |
740 | | function, |
741 | | value_16bit ); |
742 | | |
743 | | libcnotify_printf( |
744 | | "\n" ); |
745 | | } |
746 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
747 | | |
748 | 2.28k | if( ( volume_header->bytes_per_sector != 512 ) |
749 | 2.28k | && ( volume_header->bytes_per_sector != 1024 ) |
750 | 2.28k | && ( volume_header->bytes_per_sector != 2048 ) |
751 | 2.28k | && ( volume_header->bytes_per_sector != 4096 ) ) |
752 | 50 | { |
753 | 50 | libcerror_error_set( |
754 | 50 | error, |
755 | 50 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
756 | 50 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
757 | 50 | "%s: invalid bytes per sector value out of bounds.", |
758 | 50 | function ); |
759 | | |
760 | 50 | return( -1 ); |
761 | 50 | } |
762 | 2.23k | if( total_number_of_sectors != 0 ) |
763 | 1.87k | { |
764 | 1.87k | if( total_number_of_sectors > ( (uint64_t) INT64_MAX / volume_header->bytes_per_sector ) ) |
765 | 126 | { |
766 | 126 | libcerror_error_set( |
767 | 126 | error, |
768 | 126 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
769 | 126 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
770 | 126 | "%s: invalid volume size value out of bounds.", |
771 | 126 | function ); |
772 | | |
773 | 126 | return( -1 ); |
774 | 126 | } |
775 | 1.75k | volume_header->volume_size = total_number_of_sectors * volume_header->bytes_per_sector; |
776 | 1.75k | } |
777 | 2.10k | if( volume_header->version == LIBBDE_VERSION_WINDOWS_VISTA ) |
778 | 84 | { |
779 | 84 | if( volume_header->sectors_per_cluster_block == 0 ) |
780 | 1 | { |
781 | 1 | libcerror_error_set( |
782 | 1 | error, |
783 | 1 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
784 | 1 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
785 | 1 | "%s: invalid sectors per cluster block value out of bounds.", |
786 | 1 | function ); |
787 | | |
788 | 1 | return( -1 ); |
789 | 1 | } |
790 | 83 | cluster_block_size = (uint32_t) volume_header->sectors_per_cluster_block * volume_header->bytes_per_sector; |
791 | | |
792 | 83 | if( safe_first_metadata_offset > ( (uint64_t) INT64_MAX / cluster_block_size ) ) |
793 | 61 | { |
794 | 61 | libcerror_error_set( |
795 | 61 | error, |
796 | 61 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
797 | 61 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
798 | 61 | "%s: invalid first metadata offset value out of bounds.", |
799 | 61 | function ); |
800 | | |
801 | 61 | return( -1 ); |
802 | 61 | } |
803 | 22 | volume_header->first_metadata_offset = (off64_t) ( safe_first_metadata_offset * cluster_block_size ); |
804 | 22 | volume_header->metadata_size = 16384; |
805 | 22 | } |
806 | 2.02k | else if( ( volume_header->version == LIBBDE_VERSION_WINDOWS_7 ) |
807 | 2.02k | || ( volume_header->version == LIBBDE_VERSION_TO_GO ) ) |
808 | 2.02k | { |
809 | 2.02k | if( safe_first_metadata_offset > (uint64_t) INT64_MAX ) |
810 | 63 | { |
811 | 63 | libcerror_error_set( |
812 | 63 | error, |
813 | 63 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
814 | 63 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
815 | 63 | "%s: invalid first metadata offset value out of bounds.", |
816 | 63 | function ); |
817 | | |
818 | 63 | return( -1 ); |
819 | 63 | } |
820 | 1.96k | if( safe_second_metadata_offset > (uint64_t) INT64_MAX ) |
821 | 62 | { |
822 | 62 | libcerror_error_set( |
823 | 62 | error, |
824 | 62 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
825 | 62 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
826 | 62 | "%s: invalid second metadata offset value out of bounds.", |
827 | 62 | function ); |
828 | | |
829 | 62 | return( -1 ); |
830 | 62 | } |
831 | 1.90k | if( safe_third_metadata_offset > (uint64_t) INT64_MAX ) |
832 | 62 | { |
833 | 62 | libcerror_error_set( |
834 | 62 | error, |
835 | 62 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
836 | 62 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
837 | 62 | "%s: invalid third metadata offset value out of bounds.", |
838 | 62 | function ); |
839 | | |
840 | 62 | return( -1 ); |
841 | 62 | } |
842 | 1.83k | volume_header->first_metadata_offset = (off64_t) safe_first_metadata_offset; |
843 | 1.83k | volume_header->second_metadata_offset = (off64_t) safe_second_metadata_offset; |
844 | 1.83k | volume_header->third_metadata_offset = (off64_t) safe_third_metadata_offset; |
845 | 1.83k | volume_header->metadata_size = 65536; |
846 | 1.83k | } |
847 | | #if defined( HAVE_DEBUG_OUTPUT ) |
848 | | if( libcnotify_verbose != 0 ) |
849 | | { |
850 | | libcnotify_printf( |
851 | | "%s: volume size\t\t\t\t: %" PRIu64 "\n", |
852 | | function, |
853 | | volume_header->volume_size ); |
854 | | |
855 | | libcnotify_printf( |
856 | | "\n" ); |
857 | | } |
858 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
859 | | |
860 | 1.86k | return( 1 ); |
861 | 2.10k | } |
862 | | |
863 | | /* Reads the volume header |
864 | | * Returns 1 if successful or -1 on error |
865 | | */ |
866 | | int libbde_volume_header_read_file_io_handle( |
867 | | libbde_volume_header_t *volume_header, |
868 | | libbfio_handle_t *file_io_handle, |
869 | | off64_t file_offset, |
870 | | libcerror_error_t **error ) |
871 | 2.43k | { |
872 | 2.43k | uint8_t volume_header_data[ 512 ]; |
873 | | |
874 | 2.43k | static char *function = "libbde_volume_header_read_file_io_handle"; |
875 | 2.43k | ssize_t read_count = 0; |
876 | | |
877 | 2.43k | if( volume_header == NULL ) |
878 | 0 | { |
879 | 0 | libcerror_error_set( |
880 | 0 | error, |
881 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
882 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
883 | 0 | "%s: invalid volume header.", |
884 | 0 | function ); |
885 | |
|
886 | 0 | return( -1 ); |
887 | 0 | } |
888 | | #if defined( HAVE_DEBUG_OUTPUT ) |
889 | | if( libcnotify_verbose != 0 ) |
890 | | { |
891 | | libcnotify_printf( |
892 | | "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
893 | | function, |
894 | | file_offset, |
895 | | file_offset ); |
896 | | } |
897 | | #endif |
898 | 2.43k | read_count = libbfio_handle_read_buffer_at_offset( |
899 | 2.43k | file_io_handle, |
900 | 2.43k | (uint8_t *) &volume_header_data, |
901 | 2.43k | 512, |
902 | 2.43k | file_offset, |
903 | 2.43k | error ); |
904 | | |
905 | 2.43k | if( read_count != (ssize_t) 512 ) |
906 | 16 | { |
907 | 16 | libcerror_error_set( |
908 | 16 | error, |
909 | 16 | LIBCERROR_ERROR_DOMAIN_IO, |
910 | 16 | LIBCERROR_IO_ERROR_READ_FAILED, |
911 | 16 | "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
912 | 16 | function, |
913 | 16 | file_offset, |
914 | 16 | file_offset ); |
915 | | |
916 | 16 | return( -1 ); |
917 | 16 | } |
918 | 2.41k | if( libbde_volume_header_read_data( |
919 | 2.41k | volume_header, |
920 | 2.41k | (uint8_t *) &volume_header_data, |
921 | 2.41k | 512, |
922 | 2.41k | error ) != 1 ) |
923 | 555 | { |
924 | 555 | libcerror_error_set( |
925 | 555 | error, |
926 | 555 | LIBCERROR_ERROR_DOMAIN_IO, |
927 | 555 | LIBCERROR_IO_ERROR_READ_FAILED, |
928 | 555 | "%s: unable to read volume header data.", |
929 | 555 | function ); |
930 | | |
931 | 555 | return( -1 ); |
932 | 555 | } |
933 | 1.86k | return( 1 ); |
934 | 2.41k | } |
935 | | |