/src/libexe/libexe/libexe_coff_optional_header.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * COFF optional 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 "libexe_coff_optional_header.h" |
28 | | #include "libexe_data_directory_descriptor.h" |
29 | | #include "libexe_debug.h" |
30 | | #include "libexe_definitions.h" |
31 | | #include "libexe_libcerror.h" |
32 | | #include "libexe_libcnotify.h" |
33 | | |
34 | | #include "exe_file_header.h" |
35 | | |
36 | | /* Creates a COFF optional header |
37 | | * Make sure the value coff_optional_header is referencing, is set to NULL |
38 | | * Returns 1 if successful or -1 on error |
39 | | */ |
40 | | int libexe_coff_optional_header_initialize( |
41 | | libexe_coff_optional_header_t **coff_optional_header, |
42 | | libcerror_error_t **error ) |
43 | 607 | { |
44 | 607 | static char *function = "libexe_coff_optional_header_initialize"; |
45 | | |
46 | 607 | if( coff_optional_header == NULL ) |
47 | 0 | { |
48 | 0 | libcerror_error_set( |
49 | 0 | error, |
50 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
51 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
52 | 0 | "%s: invalid COFF optional header.", |
53 | 0 | function ); |
54 | |
|
55 | 0 | return( -1 ); |
56 | 0 | } |
57 | 607 | if( *coff_optional_header != NULL ) |
58 | 0 | { |
59 | 0 | libcerror_error_set( |
60 | 0 | error, |
61 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
62 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
63 | 0 | "%s: invalid COFF optional header value already set.", |
64 | 0 | function ); |
65 | |
|
66 | 0 | return( -1 ); |
67 | 0 | } |
68 | 607 | *coff_optional_header = memory_allocate_structure( |
69 | 607 | libexe_coff_optional_header_t ); |
70 | | |
71 | 607 | if( *coff_optional_header == NULL ) |
72 | 0 | { |
73 | 0 | libcerror_error_set( |
74 | 0 | error, |
75 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
76 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
77 | 0 | "%s: unable to create COFF optional header.", |
78 | 0 | function ); |
79 | |
|
80 | 0 | goto on_error; |
81 | 0 | } |
82 | 607 | if( memory_set( |
83 | 607 | *coff_optional_header, |
84 | 607 | 0, |
85 | 607 | sizeof( libexe_coff_optional_header_t ) ) == NULL ) |
86 | 0 | { |
87 | 0 | libcerror_error_set( |
88 | 0 | error, |
89 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
90 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
91 | 0 | "%s: unable to clear file.", |
92 | 0 | function ); |
93 | |
|
94 | 0 | goto on_error; |
95 | 0 | } |
96 | 607 | return( 1 ); |
97 | | |
98 | 0 | on_error: |
99 | 0 | if( *coff_optional_header != NULL ) |
100 | 0 | { |
101 | 0 | memory_free( |
102 | 0 | *coff_optional_header ); |
103 | |
|
104 | 0 | *coff_optional_header = NULL; |
105 | 0 | } |
106 | 0 | return( -1 ); |
107 | 607 | } |
108 | | |
109 | | /* Frees a COFF optional header |
110 | | * Returns 1 if successful or -1 on error |
111 | | */ |
112 | | int libexe_coff_optional_header_free( |
113 | | libexe_coff_optional_header_t **coff_optional_header, |
114 | | libcerror_error_t **error ) |
115 | 607 | { |
116 | 607 | static char *function = "libexe_coff_optional_header_free"; |
117 | | |
118 | 607 | if( coff_optional_header == NULL ) |
119 | 0 | { |
120 | 0 | libcerror_error_set( |
121 | 0 | error, |
122 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
123 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
124 | 0 | "%s: invalid COFF optional header.", |
125 | 0 | function ); |
126 | |
|
127 | 0 | return( -1 ); |
128 | 0 | } |
129 | 607 | if( *coff_optional_header != NULL ) |
130 | 607 | { |
131 | 607 | memory_free( |
132 | 607 | *coff_optional_header ); |
133 | | |
134 | 607 | *coff_optional_header = NULL; |
135 | 607 | } |
136 | 607 | return( 1 ); |
137 | 607 | } |
138 | | |
139 | | /* Reads the COFF optional header |
140 | | * Returns 1 if successful or -1 on error |
141 | | */ |
142 | | int libexe_coff_optional_header_read_data( |
143 | | libexe_coff_optional_header_t *coff_optional_header, |
144 | | const uint8_t *data, |
145 | | size_t data_size, |
146 | | libcerror_error_t **error ) |
147 | 590 | { |
148 | 590 | libexe_data_directory_descriptor_t *data_directory_descriptor = NULL; |
149 | 590 | static char *function = "libexe_coff_optional_header_read_data"; |
150 | 590 | size_t data_offset = 0; |
151 | 590 | uint32_t number_of_data_directories_entries = 0; |
152 | 590 | uint16_t signature = 0; |
153 | | |
154 | | #if defined( HAVE_DEBUG_OUTPUT ) |
155 | | uint64_t value_64bit = 0; |
156 | | uint32_t value_32bit = 0; |
157 | | uint16_t value_16bit = 0; |
158 | | #endif |
159 | | |
160 | 590 | if( coff_optional_header == NULL ) |
161 | 0 | { |
162 | 0 | libcerror_error_set( |
163 | 0 | error, |
164 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
165 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
166 | 0 | "%s: invalid COFF optional header.", |
167 | 0 | function ); |
168 | |
|
169 | 0 | return( -1 ); |
170 | 0 | } |
171 | 590 | if( data == NULL ) |
172 | 0 | { |
173 | 0 | libcerror_error_set( |
174 | 0 | error, |
175 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
176 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
177 | 0 | "%s: invalid data.", |
178 | 0 | function ); |
179 | |
|
180 | 0 | return( -1 ); |
181 | 0 | } |
182 | 590 | if( ( data_size < sizeof( exe_coff_optional_header_t ) ) |
183 | 590 | || ( data_size > (size_t) SSIZE_MAX ) ) |
184 | 5 | { |
185 | 5 | libcerror_error_set( |
186 | 5 | error, |
187 | 5 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
188 | 5 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
189 | 5 | "%s: invalid data size value out of bounds.", |
190 | 5 | function ); |
191 | | |
192 | 5 | return( -1 ); |
193 | 5 | } |
194 | | #if defined( HAVE_DEBUG_OUTPUT ) |
195 | | if( libcnotify_verbose != 0 ) |
196 | | { |
197 | | libcnotify_printf( |
198 | | "%s: COFF optional header:\n", |
199 | | function ); |
200 | | libcnotify_print_data( |
201 | | data, |
202 | | data_size, |
203 | | 0 ); |
204 | | } |
205 | | #endif |
206 | 585 | byte_stream_copy_to_uint16_little_endian( |
207 | 585 | ( (exe_coff_optional_header_t *) data )->signature, |
208 | 585 | signature ); |
209 | | |
210 | | #if defined( HAVE_DEBUG_OUTPUT ) |
211 | | if( libcnotify_verbose != 0 ) |
212 | | { |
213 | | libcnotify_printf( |
214 | | "%s: signature\t\t\t: 0x%04" PRIx16 "\n", |
215 | | function, |
216 | | signature ); |
217 | | |
218 | | libcnotify_printf( |
219 | | "%s: major linker version\t\t: %" PRIu8 "\n", |
220 | | function, |
221 | | ( (exe_coff_optional_header_t *) data )->major_linker_version ); |
222 | | |
223 | | libcnotify_printf( |
224 | | "%s: minor linker version\t\t: %" PRIu8 "\n", |
225 | | function, |
226 | | ( (exe_coff_optional_header_t *) data )->minor_linker_version ); |
227 | | |
228 | | byte_stream_copy_to_uint32_little_endian( |
229 | | ( (exe_coff_optional_header_t *) data )->text_section_size, |
230 | | value_32bit ); |
231 | | libcnotify_printf( |
232 | | "%s: text section size\t\t: %" PRIu32 "\n", |
233 | | function, |
234 | | value_32bit ); |
235 | | |
236 | | byte_stream_copy_to_uint32_little_endian( |
237 | | ( (exe_coff_optional_header_t *) data )->initialized_data_section_size, |
238 | | value_32bit ); |
239 | | libcnotify_printf( |
240 | | "%s: initialized data section size\t: %" PRIu32 "\n", |
241 | | function, |
242 | | value_32bit ); |
243 | | |
244 | | byte_stream_copy_to_uint32_little_endian( |
245 | | ( (exe_coff_optional_header_t *) data )->uninitialized_data_section_size, |
246 | | value_32bit ); |
247 | | libcnotify_printf( |
248 | | "%s: uninitialized data section size\t: %" PRIu32 "\n", |
249 | | function, |
250 | | value_32bit ); |
251 | | |
252 | | byte_stream_copy_to_uint32_little_endian( |
253 | | ( (exe_coff_optional_header_t *) data )->entry_point_offset, |
254 | | value_32bit ); |
255 | | libcnotify_printf( |
256 | | "%s: entry point offset\t\t: 0x%08" PRIx32 "\n", |
257 | | function, |
258 | | value_32bit ); |
259 | | |
260 | | byte_stream_copy_to_uint32_little_endian( |
261 | | ( (exe_coff_optional_header_t *) data )->code_base_offset, |
262 | | value_32bit ); |
263 | | libcnotify_printf( |
264 | | "%s: code base offset\t\t\t: 0x%08" PRIx32 "\n", |
265 | | function, |
266 | | value_32bit ); |
267 | | |
268 | | if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 ) |
269 | | { |
270 | | byte_stream_copy_to_uint32_little_endian( |
271 | | ( (exe_coff_optional_header_t *) data )->data_base_offset, |
272 | | value_32bit ); |
273 | | libcnotify_printf( |
274 | | "%s: data base offset\t\t\t: 0x%08" PRIx32 "\n", |
275 | | function, |
276 | | value_32bit ); |
277 | | } |
278 | | libcnotify_printf( |
279 | | "\n" ); |
280 | | } |
281 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
282 | | |
283 | 585 | if( ( signature != LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 ) |
284 | 585 | && ( signature != LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32_PLUS ) ) |
285 | 32 | { |
286 | 32 | libcerror_error_set( |
287 | 32 | error, |
288 | 32 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
289 | 32 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
290 | 32 | "%s: unsupported signature.", |
291 | 32 | function ); |
292 | | |
293 | 32 | return( -1 ); |
294 | 32 | } |
295 | 553 | data_offset = sizeof( exe_coff_optional_header_t ); |
296 | | |
297 | 553 | if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 ) |
298 | 546 | { |
299 | 546 | if( sizeof( exe_coff_optional_header_pe32_t ) > ( data_size - data_offset ) ) |
300 | 7 | { |
301 | 7 | libcerror_error_set( |
302 | 7 | error, |
303 | 7 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
304 | 7 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
305 | 7 | "%s: invalid data size value too small.", |
306 | 7 | function ); |
307 | | |
308 | 7 | return( -1 ); |
309 | 7 | } |
310 | 539 | byte_stream_copy_to_uint32_little_endian( |
311 | 539 | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->number_of_data_directories_entries, |
312 | 539 | number_of_data_directories_entries ); |
313 | | |
314 | | #if defined( HAVE_DEBUG_OUTPUT ) |
315 | | if( libcnotify_verbose != 0 ) |
316 | | { |
317 | | byte_stream_copy_to_uint32_little_endian( |
318 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->image_base_offset, |
319 | | value_32bit ); |
320 | | libcnotify_printf( |
321 | | "%s: image base offset\t\t: 0x%08" PRIx32 "\n", |
322 | | function, |
323 | | value_32bit ); |
324 | | |
325 | | byte_stream_copy_to_uint32_little_endian( |
326 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->section_alignment_size, |
327 | | value_32bit ); |
328 | | libcnotify_printf( |
329 | | "%s: section alignment size\t\t: %" PRIu32 "\n", |
330 | | function, |
331 | | value_32bit ); |
332 | | |
333 | | byte_stream_copy_to_uint32_little_endian( |
334 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->file_alignment_size, |
335 | | value_32bit ); |
336 | | libcnotify_printf( |
337 | | "%s: file alignment size\t\t: %" PRIu32 "\n", |
338 | | function, |
339 | | value_32bit ); |
340 | | |
341 | | byte_stream_copy_to_uint16_little_endian( |
342 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_operating_system_version, |
343 | | value_16bit ); |
344 | | libcnotify_printf( |
345 | | "%s: major operating system version\t: %" PRIu16 "\n", |
346 | | function, |
347 | | value_16bit ); |
348 | | |
349 | | byte_stream_copy_to_uint16_little_endian( |
350 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_operating_system_version, |
351 | | value_16bit ); |
352 | | libcnotify_printf( |
353 | | "%s: minor operating system version\t: %" PRIu16 "\n", |
354 | | function, |
355 | | value_16bit ); |
356 | | |
357 | | byte_stream_copy_to_uint16_little_endian( |
358 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_image_version, |
359 | | value_16bit ); |
360 | | libcnotify_printf( |
361 | | "%s: major image version\t\t: %" PRIu16 "\n", |
362 | | function, |
363 | | value_16bit ); |
364 | | |
365 | | byte_stream_copy_to_uint16_little_endian( |
366 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_image_version, |
367 | | value_16bit ); |
368 | | libcnotify_printf( |
369 | | "%s: minor image version\t\t: %" PRIu16 "\n", |
370 | | function, |
371 | | value_16bit ); |
372 | | |
373 | | byte_stream_copy_to_uint16_little_endian( |
374 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_subsystem_version, |
375 | | value_16bit ); |
376 | | libcnotify_printf( |
377 | | "%s: major subsystem version\t\t: %" PRIu16 "\n", |
378 | | function, |
379 | | value_16bit ); |
380 | | |
381 | | byte_stream_copy_to_uint16_little_endian( |
382 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_subsystem_version, |
383 | | value_16bit ); |
384 | | libcnotify_printf( |
385 | | "%s: minor subsystem version\t\t: %" PRIu16 "\n", |
386 | | function, |
387 | | value_16bit ); |
388 | | |
389 | | byte_stream_copy_to_uint32_little_endian( |
390 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->unknown1, |
391 | | value_32bit ); |
392 | | libcnotify_printf( |
393 | | "%s: unknown1\t\t\t\t: %" PRIu32 "\n", |
394 | | function, |
395 | | value_32bit ); |
396 | | |
397 | | byte_stream_copy_to_uint32_little_endian( |
398 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->image_size, |
399 | | value_32bit ); |
400 | | libcnotify_printf( |
401 | | "%s: image size\t\t\t: %" PRIu32 "\n", |
402 | | function, |
403 | | value_32bit ); |
404 | | |
405 | | byte_stream_copy_to_uint32_little_endian( |
406 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->headers_size, |
407 | | value_32bit ); |
408 | | libcnotify_printf( |
409 | | "%s: headers size\t\t\t: %" PRIu32 "\n", |
410 | | function, |
411 | | value_32bit ); |
412 | | |
413 | | byte_stream_copy_to_uint32_little_endian( |
414 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->checksum, |
415 | | value_32bit ); |
416 | | libcnotify_printf( |
417 | | "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", |
418 | | function, |
419 | | value_32bit ); |
420 | | |
421 | | byte_stream_copy_to_uint16_little_endian( |
422 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->subsystem, |
423 | | value_16bit ); |
424 | | libcnotify_printf( |
425 | | "%s: subsystem\t\t\t: 0x%04" PRIx16 "\n", |
426 | | function, |
427 | | value_16bit ); |
428 | | |
429 | | byte_stream_copy_to_uint16_little_endian( |
430 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->dll_characteristic_flags, |
431 | | value_16bit ); |
432 | | libcnotify_printf( |
433 | | "%s: DLL characteristic flags\t\t: 0x%04" PRIx16 "\n", |
434 | | function, |
435 | | value_16bit ); |
436 | | libexe_debug_print_dll_characteristic_flags( |
437 | | value_16bit ); |
438 | | libcnotify_printf( |
439 | | "\n" ); |
440 | | |
441 | | byte_stream_copy_to_uint32_little_endian( |
442 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->stack_reservation_size, |
443 | | value_32bit ); |
444 | | libcnotify_printf( |
445 | | "%s: stack reservation size\t\t: %" PRIu32 "\n", |
446 | | function, |
447 | | value_32bit ); |
448 | | |
449 | | byte_stream_copy_to_uint32_little_endian( |
450 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->stack_commit_size, |
451 | | value_32bit ); |
452 | | libcnotify_printf( |
453 | | "%s: stack commit size\t\t: %" PRIu32 "\n", |
454 | | function, |
455 | | value_32bit ); |
456 | | |
457 | | byte_stream_copy_to_uint32_little_endian( |
458 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->heap_reservation_size, |
459 | | value_32bit ); |
460 | | libcnotify_printf( |
461 | | "%s: heap reservation size\t\t: %" PRIu32 "\n", |
462 | | function, |
463 | | value_32bit ); |
464 | | |
465 | | byte_stream_copy_to_uint32_little_endian( |
466 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->heap_commit_size, |
467 | | value_32bit ); |
468 | | libcnotify_printf( |
469 | | "%s: heap commit size\t\t\t: %" PRIu32 "\n", |
470 | | function, |
471 | | value_32bit ); |
472 | | |
473 | | byte_stream_copy_to_uint32_little_endian( |
474 | | ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->unknown2, |
475 | | value_32bit ); |
476 | | libcnotify_printf( |
477 | | "%s: unknown2\t\t\t\t: %" PRIu32 "\n", |
478 | | function, |
479 | | value_32bit ); |
480 | | |
481 | | libcnotify_printf( |
482 | | "%s: number of data directory entries\t: %" PRIu32 "\n", |
483 | | function, |
484 | | number_of_data_directories_entries ); |
485 | | } |
486 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
487 | | |
488 | 539 | data_offset += sizeof( exe_coff_optional_header_pe32_t ); |
489 | 539 | } |
490 | 7 | else if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 ) |
491 | 0 | { |
492 | 0 | if( sizeof( exe_coff_optional_header_pe32_plus_t ) > ( data_size - data_offset ) ) |
493 | 0 | { |
494 | 0 | libcerror_error_set( |
495 | 0 | error, |
496 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
497 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
498 | 0 | "%s: invalid data size value too small.", |
499 | 0 | function ); |
500 | |
|
501 | 0 | return( -1 ); |
502 | 0 | } |
503 | 0 | byte_stream_copy_to_uint32_little_endian( |
504 | 0 | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->number_of_data_directories_entries, |
505 | 0 | number_of_data_directories_entries ); |
506 | |
|
507 | | #if defined( HAVE_DEBUG_OUTPUT ) |
508 | | if( libcnotify_verbose != 0 ) |
509 | | { |
510 | | byte_stream_copy_to_uint64_little_endian( |
511 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->image_base_offset, |
512 | | value_64bit ); |
513 | | libcnotify_printf( |
514 | | "%s: image base offset\t\t: 0x%08" PRIx64 "\n", |
515 | | function, |
516 | | value_64bit ); |
517 | | |
518 | | byte_stream_copy_to_uint32_little_endian( |
519 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->section_alignment_size, |
520 | | value_32bit ); |
521 | | libcnotify_printf( |
522 | | "%s: section alignment size\t\t: %" PRIu32 "\n", |
523 | | function, |
524 | | value_32bit ); |
525 | | |
526 | | byte_stream_copy_to_uint32_little_endian( |
527 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->file_alignment_size, |
528 | | value_32bit ); |
529 | | libcnotify_printf( |
530 | | "%s: file alignment size\t\t: %" PRIu32 "\n", |
531 | | function, |
532 | | value_32bit ); |
533 | | |
534 | | byte_stream_copy_to_uint16_little_endian( |
535 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_operating_system_version, |
536 | | value_16bit ); |
537 | | libcnotify_printf( |
538 | | "%s: major operating system version\t: %" PRIu16 "\n", |
539 | | function, |
540 | | value_16bit ); |
541 | | |
542 | | byte_stream_copy_to_uint16_little_endian( |
543 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_operating_system_version, |
544 | | value_16bit ); |
545 | | libcnotify_printf( |
546 | | "%s: minor operating system version\t: %" PRIu16 "\n", |
547 | | function, |
548 | | value_16bit ); |
549 | | |
550 | | byte_stream_copy_to_uint16_little_endian( |
551 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_image_version, |
552 | | value_16bit ); |
553 | | libcnotify_printf( |
554 | | "%s: major image version\t\t: %" PRIu16 "\n", |
555 | | function, |
556 | | value_16bit ); |
557 | | |
558 | | byte_stream_copy_to_uint16_little_endian( |
559 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_image_version, |
560 | | value_16bit ); |
561 | | libcnotify_printf( |
562 | | "%s: minor image version\t\t: %" PRIu16 "\n", |
563 | | function, |
564 | | value_16bit ); |
565 | | |
566 | | byte_stream_copy_to_uint16_little_endian( |
567 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_subsystem_version, |
568 | | value_16bit ); |
569 | | libcnotify_printf( |
570 | | "%s: major subsystem version\t\t: %" PRIu16 "\n", |
571 | | function, |
572 | | value_16bit ); |
573 | | |
574 | | byte_stream_copy_to_uint16_little_endian( |
575 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_subsystem_version, |
576 | | value_16bit ); |
577 | | libcnotify_printf( |
578 | | "%s: minor subsystem version\t\t: %" PRIu16 "\n", |
579 | | function, |
580 | | value_16bit ); |
581 | | |
582 | | byte_stream_copy_to_uint32_little_endian( |
583 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->unknown1, |
584 | | value_32bit ); |
585 | | libcnotify_printf( |
586 | | "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n", |
587 | | function, |
588 | | value_32bit ); |
589 | | |
590 | | byte_stream_copy_to_uint32_little_endian( |
591 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->image_size, |
592 | | value_32bit ); |
593 | | libcnotify_printf( |
594 | | "%s: image size\t\t\t: %" PRIu32 "\n", |
595 | | function, |
596 | | value_32bit ); |
597 | | |
598 | | byte_stream_copy_to_uint32_little_endian( |
599 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->headers_size, |
600 | | value_32bit ); |
601 | | libcnotify_printf( |
602 | | "%s: headers size\t\t\t: %" PRIu32 "\n", |
603 | | function, |
604 | | value_32bit ); |
605 | | |
606 | | byte_stream_copy_to_uint32_little_endian( |
607 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->checksum, |
608 | | value_32bit ); |
609 | | libcnotify_printf( |
610 | | "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", |
611 | | function, |
612 | | value_32bit ); |
613 | | |
614 | | byte_stream_copy_to_uint16_little_endian( |
615 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->subsystem, |
616 | | value_16bit ); |
617 | | libcnotify_printf( |
618 | | "%s: subsystem\t\t\t: 0x%04" PRIx16 "\n", |
619 | | function, |
620 | | value_16bit ); |
621 | | |
622 | | byte_stream_copy_to_uint16_little_endian( |
623 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->dll_characteristic_flags, |
624 | | value_16bit ); |
625 | | libcnotify_printf( |
626 | | "%s: DLL characteristic flags\t\t: 0x%04" PRIx16 "\n", |
627 | | function, |
628 | | value_16bit ); |
629 | | libexe_debug_print_dll_characteristic_flags( |
630 | | value_16bit ); |
631 | | libcnotify_printf( |
632 | | "\n" ); |
633 | | |
634 | | byte_stream_copy_to_uint64_little_endian( |
635 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->stack_reservation_size, |
636 | | value_64bit ); |
637 | | libcnotify_printf( |
638 | | "%s: stack reservation size\t\t: %" PRIu64 "\n", |
639 | | function, |
640 | | value_64bit ); |
641 | | |
642 | | byte_stream_copy_to_uint64_little_endian( |
643 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->stack_commit_size, |
644 | | value_64bit ); |
645 | | libcnotify_printf( |
646 | | "%s: stack commit size\t\t: %" PRIu64 "\n", |
647 | | function, |
648 | | value_64bit ); |
649 | | |
650 | | byte_stream_copy_to_uint64_little_endian( |
651 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->heap_reservation_size, |
652 | | value_64bit ); |
653 | | libcnotify_printf( |
654 | | "%s: heap reservation size\t\t: %" PRIu64 "\n", |
655 | | function, |
656 | | value_64bit ); |
657 | | |
658 | | byte_stream_copy_to_uint64_little_endian( |
659 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->heap_commit_size, |
660 | | value_64bit ); |
661 | | libcnotify_printf( |
662 | | "%s: heap commit size\t\t\t: %" PRIu64 "\n", |
663 | | function, |
664 | | value_64bit ); |
665 | | |
666 | | byte_stream_copy_to_uint32_little_endian( |
667 | | ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->unknown2, |
668 | | value_32bit ); |
669 | | libcnotify_printf( |
670 | | "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n", |
671 | | function, |
672 | | value_32bit ); |
673 | | |
674 | | libcnotify_printf( |
675 | | "%s: number of data directory entries\t: %" PRIu32 "\n", |
676 | | function, |
677 | | number_of_data_directories_entries ); |
678 | | } |
679 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
680 | |
|
681 | 0 | data_offset += sizeof( exe_coff_optional_header_pe32_plus_t ); |
682 | 0 | } |
683 | | #if defined( HAVE_DEBUG_OUTPUT ) |
684 | | if( libcnotify_verbose != 0 ) |
685 | | { |
686 | | libcnotify_printf( |
687 | | "\n" ); |
688 | | } |
689 | | #endif |
690 | 546 | if( number_of_data_directories_entries > 16 ) |
691 | 36 | { |
692 | 36 | libcerror_error_set( |
693 | 36 | error, |
694 | 36 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
695 | 36 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
696 | 36 | "%s: unsupported number of data directory entries: %" PRIu32 ".", |
697 | 36 | function, |
698 | 36 | number_of_data_directories_entries ); |
699 | | |
700 | 36 | return( -1 ); |
701 | 36 | } |
702 | 510 | if( ( (size_t) number_of_data_directories_entries * 8 ) > ( data_size - data_offset ) ) |
703 | 5 | { |
704 | 5 | libcerror_error_set( |
705 | 5 | error, |
706 | 5 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
707 | 5 | LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL, |
708 | 5 | "%s: invalid data size value too small.", |
709 | 5 | function ); |
710 | | |
711 | 5 | return( -1 ); |
712 | 5 | } |
713 | 505 | if( number_of_data_directories_entries > 0 ) |
714 | 473 | { |
715 | 473 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXPORT_TABLE ] ); |
716 | | |
717 | 473 | byte_stream_copy_to_uint32_little_endian( |
718 | 473 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_rva, |
719 | 473 | data_directory_descriptor->virtual_address ); |
720 | | |
721 | 473 | byte_stream_copy_to_uint32_little_endian( |
722 | 473 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_size, |
723 | 473 | data_directory_descriptor->size ); |
724 | | |
725 | | #if defined( HAVE_DEBUG_OUTPUT ) |
726 | | if( libcnotify_verbose != 0 ) |
727 | | { |
728 | | libcnotify_printf( |
729 | | "%s: export table RVA\t\t\t: 0x%08" PRIx32 "\n", |
730 | | function, |
731 | | data_directory_descriptor->virtual_address ); |
732 | | |
733 | | libcnotify_printf( |
734 | | "%s: export table size\t\t: %" PRIu32 "\n", |
735 | | function, |
736 | | data_directory_descriptor->size ); |
737 | | } |
738 | | #endif |
739 | 473 | number_of_data_directories_entries--; |
740 | 473 | } |
741 | 505 | if( number_of_data_directories_entries > 0 ) |
742 | 327 | { |
743 | 327 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_TABLE ] ); |
744 | | |
745 | 327 | byte_stream_copy_to_uint32_little_endian( |
746 | 327 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_rva, |
747 | 327 | data_directory_descriptor->virtual_address ); |
748 | | |
749 | 327 | byte_stream_copy_to_uint32_little_endian( |
750 | 327 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_size, |
751 | 327 | data_directory_descriptor->size ); |
752 | | |
753 | | #if defined( HAVE_DEBUG_OUTPUT ) |
754 | | if( libcnotify_verbose != 0 ) |
755 | | { |
756 | | libcnotify_printf( |
757 | | "%s: import table RVA\t\t\t: 0x%08" PRIx32 "\n", |
758 | | function, |
759 | | data_directory_descriptor->virtual_address ); |
760 | | |
761 | | libcnotify_printf( |
762 | | "%s: import table size\t\t: %" PRIu32 "\n", |
763 | | function, |
764 | | data_directory_descriptor->size ); |
765 | | } |
766 | | #endif |
767 | 327 | number_of_data_directories_entries--; |
768 | 327 | } |
769 | 505 | if( number_of_data_directories_entries > 0 ) |
770 | 212 | { |
771 | 212 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_RESOURCE_TABLE ] ); |
772 | | |
773 | 212 | byte_stream_copy_to_uint32_little_endian( |
774 | 212 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_rva, |
775 | 212 | data_directory_descriptor->virtual_address ); |
776 | | |
777 | 212 | byte_stream_copy_to_uint32_little_endian( |
778 | 212 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_size, |
779 | 212 | data_directory_descriptor->size ); |
780 | | |
781 | | #if defined( HAVE_DEBUG_OUTPUT ) |
782 | | if( libcnotify_verbose != 0 ) |
783 | | { |
784 | | libcnotify_printf( |
785 | | "%s: resource table RVA\t\t: 0x%08" PRIx32 "\n", |
786 | | function, |
787 | | data_directory_descriptor->virtual_address ); |
788 | | |
789 | | libcnotify_printf( |
790 | | "%s: resource table size\t\t: %" PRIu32 "\n", |
791 | | function, |
792 | | data_directory_descriptor->size ); |
793 | | } |
794 | | #endif |
795 | 212 | number_of_data_directories_entries--; |
796 | 212 | } |
797 | 505 | if( number_of_data_directories_entries > 0 ) |
798 | 198 | { |
799 | 198 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXCEPTION_TABLE ] ); |
800 | | |
801 | 198 | byte_stream_copy_to_uint32_little_endian( |
802 | 198 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_rva, |
803 | 198 | data_directory_descriptor->virtual_address ); |
804 | | |
805 | 198 | byte_stream_copy_to_uint32_little_endian( |
806 | 198 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_size, |
807 | 198 | data_directory_descriptor->size ); |
808 | | |
809 | | #if defined( HAVE_DEBUG_OUTPUT ) |
810 | | if( libcnotify_verbose != 0 ) |
811 | | { |
812 | | libcnotify_printf( |
813 | | "%s: exception table RVA\t\t: 0x%08" PRIx32 "\n", |
814 | | function, |
815 | | data_directory_descriptor->virtual_address ); |
816 | | |
817 | | libcnotify_printf( |
818 | | "%s: exception table size\t\t: %" PRIu32 "\n", |
819 | | function, |
820 | | data_directory_descriptor->size ); |
821 | | } |
822 | | #endif |
823 | 198 | number_of_data_directories_entries--; |
824 | 198 | } |
825 | 505 | if( number_of_data_directories_entries > 0 ) |
826 | 197 | { |
827 | 197 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_CERTIFICATE_TABLE ] ); |
828 | | |
829 | 197 | byte_stream_copy_to_uint32_little_endian( |
830 | 197 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_rva, |
831 | 197 | data_directory_descriptor->virtual_address ); |
832 | | |
833 | 197 | byte_stream_copy_to_uint32_little_endian( |
834 | 197 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_size, |
835 | 197 | data_directory_descriptor->size ); |
836 | | |
837 | | #if defined( HAVE_DEBUG_OUTPUT ) |
838 | | if( libcnotify_verbose != 0 ) |
839 | | { |
840 | | libcnotify_printf( |
841 | | "%s: certificate table RVA\t\t: 0x%08" PRIx32 "\n", |
842 | | function, |
843 | | value_32bit ); |
844 | | |
845 | | libcnotify_printf( |
846 | | "%s: certificate table size\t\t: %" PRIu32 "\n", |
847 | | function, |
848 | | value_32bit ); |
849 | | } |
850 | | #endif |
851 | 197 | number_of_data_directories_entries--; |
852 | 197 | } |
853 | 505 | if( number_of_data_directories_entries > 0 ) |
854 | 196 | { |
855 | 196 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BASE_RELOCATION_TABLE ] ); |
856 | | |
857 | 196 | byte_stream_copy_to_uint32_little_endian( |
858 | 196 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_rva, |
859 | 196 | data_directory_descriptor->virtual_address ); |
860 | | |
861 | 196 | byte_stream_copy_to_uint32_little_endian( |
862 | 196 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_size, |
863 | 196 | data_directory_descriptor->size ); |
864 | | |
865 | | #if defined( HAVE_DEBUG_OUTPUT ) |
866 | | if( libcnotify_verbose != 0 ) |
867 | | { |
868 | | libcnotify_printf( |
869 | | "%s: base relocation table RVA\t: 0x%08" PRIx32 "\n", |
870 | | function, |
871 | | value_32bit ); |
872 | | |
873 | | libcnotify_printf( |
874 | | "%s: base relocation table size\t: %" PRIu32 "\n", |
875 | | function, |
876 | | value_32bit ); |
877 | | } |
878 | | #endif |
879 | 196 | number_of_data_directories_entries--; |
880 | 196 | } |
881 | 505 | if( number_of_data_directories_entries > 0 ) |
882 | 195 | { |
883 | 195 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DEBUG_DATA ] ); |
884 | | |
885 | 195 | byte_stream_copy_to_uint32_little_endian( |
886 | 195 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_rva, |
887 | 195 | data_directory_descriptor->virtual_address ); |
888 | | |
889 | 195 | byte_stream_copy_to_uint32_little_endian( |
890 | 195 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_size, |
891 | 195 | data_directory_descriptor->size ); |
892 | | |
893 | | #if defined( HAVE_DEBUG_OUTPUT ) |
894 | | if( libcnotify_verbose != 0 ) |
895 | | { |
896 | | libcnotify_printf( |
897 | | "%s: debug data RVA\t\t\t: 0x%08" PRIx32 "\n", |
898 | | function, |
899 | | data_directory_descriptor->virtual_address ); |
900 | | |
901 | | libcnotify_printf( |
902 | | "%s: debug data size\t\t\t: %" PRIu32 "\n", |
903 | | function, |
904 | | data_directory_descriptor->size ); |
905 | | } |
906 | | #endif |
907 | 195 | number_of_data_directories_entries--; |
908 | 195 | } |
909 | 505 | if( number_of_data_directories_entries > 0 ) |
910 | 41 | { |
911 | | #if defined( HAVE_DEBUG_OUTPUT ) |
912 | | if( libcnotify_verbose != 0 ) |
913 | | { |
914 | | byte_stream_copy_to_uint32_little_endian( |
915 | | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->architecture_specific_data_rva, |
916 | | value_32bit ); |
917 | | libcnotify_printf( |
918 | | "%s: architecture-specific data RVA\t: 0x%08" PRIx32 "\n", |
919 | | function, |
920 | | value_32bit ); |
921 | | |
922 | | byte_stream_copy_to_uint32_little_endian( |
923 | | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->architecture_specific_data_size, |
924 | | value_32bit ); |
925 | | libcnotify_printf( |
926 | | "%s: architecture-specific data size\t: %" PRIu32 "\n", |
927 | | function, |
928 | | value_32bit ); |
929 | | } |
930 | | #endif |
931 | 41 | number_of_data_directories_entries--; |
932 | 41 | } |
933 | 505 | if( number_of_data_directories_entries > 0 ) |
934 | 40 | { |
935 | | #if defined( HAVE_DEBUG_OUTPUT ) |
936 | | if( libcnotify_verbose != 0 ) |
937 | | { |
938 | | byte_stream_copy_to_uint32_little_endian( |
939 | | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->global_pointer_register, |
940 | | value_32bit ); |
941 | | libcnotify_printf( |
942 | | "%s: global pointer register\t\t: 0x%08" PRIx32 "\n", |
943 | | function, |
944 | | value_32bit ); |
945 | | |
946 | | byte_stream_copy_to_uint32_little_endian( |
947 | | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->unknown3, |
948 | | value_32bit ); |
949 | | libcnotify_printf( |
950 | | "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n", |
951 | | function, |
952 | | value_32bit ); |
953 | | } |
954 | | #endif |
955 | 40 | number_of_data_directories_entries--; |
956 | 40 | } |
957 | 505 | if( number_of_data_directories_entries > 0 ) |
958 | 39 | { |
959 | 39 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_THREAD_LOCAL_STORAGE_TABLE ] ); |
960 | | |
961 | 39 | byte_stream_copy_to_uint32_little_endian( |
962 | 39 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_rva, |
963 | 39 | data_directory_descriptor->virtual_address ); |
964 | | |
965 | 39 | byte_stream_copy_to_uint32_little_endian( |
966 | 39 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_size, |
967 | 39 | data_directory_descriptor->size ); |
968 | | |
969 | | #if defined( HAVE_DEBUG_OUTPUT ) |
970 | | if( libcnotify_verbose != 0 ) |
971 | | { |
972 | | libcnotify_printf( |
973 | | "%s: thread local storage table RVA\t: 0x%08" PRIx32 "\n", |
974 | | function, |
975 | | data_directory_descriptor->virtual_address ); |
976 | | |
977 | | libcnotify_printf( |
978 | | "%s: thread local storage table size\t: %" PRIu32 "\n", |
979 | | function, |
980 | | data_directory_descriptor->size ); |
981 | | } |
982 | | #endif |
983 | 39 | number_of_data_directories_entries--; |
984 | 39 | } |
985 | 505 | if( number_of_data_directories_entries > 0 ) |
986 | 38 | { |
987 | 38 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_LOAD_CONFIGURATION_TABLE ] ); |
988 | | |
989 | 38 | byte_stream_copy_to_uint32_little_endian( |
990 | 38 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_rva, |
991 | 38 | data_directory_descriptor->virtual_address ); |
992 | | |
993 | 38 | byte_stream_copy_to_uint32_little_endian( |
994 | 38 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_size, |
995 | 38 | data_directory_descriptor->size ); |
996 | | |
997 | | #if defined( HAVE_DEBUG_OUTPUT ) |
998 | | if( libcnotify_verbose != 0 ) |
999 | | { |
1000 | | libcnotify_printf( |
1001 | | "%s: load configuration table RVA\t: 0x%08" PRIx32 "\n", |
1002 | | function, |
1003 | | data_directory_descriptor->virtual_address ); |
1004 | | |
1005 | | libcnotify_printf( |
1006 | | "%s: load configuration table size\t: %" PRIu32 "\n", |
1007 | | function, |
1008 | | data_directory_descriptor->size ); |
1009 | | } |
1010 | | #endif |
1011 | 38 | number_of_data_directories_entries--; |
1012 | 38 | } |
1013 | 505 | if( number_of_data_directories_entries > 0 ) |
1014 | 37 | { |
1015 | 37 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BOUND_IMPORT_TABLE ] ); |
1016 | | |
1017 | 37 | byte_stream_copy_to_uint32_little_endian( |
1018 | 37 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_rva, |
1019 | 37 | data_directory_descriptor->virtual_address ); |
1020 | | |
1021 | 37 | byte_stream_copy_to_uint32_little_endian( |
1022 | 37 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_size, |
1023 | 37 | data_directory_descriptor->size ); |
1024 | | |
1025 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1026 | | if( libcnotify_verbose != 0 ) |
1027 | | { |
1028 | | libcnotify_printf( |
1029 | | "%s: bound import table RVA\t\t: 0x%08" PRIx32 "\n", |
1030 | | function, |
1031 | | data_directory_descriptor->virtual_address ); |
1032 | | |
1033 | | libcnotify_printf( |
1034 | | "%s: bound import table size\t\t: %" PRIu32 "\n", |
1035 | | function, |
1036 | | data_directory_descriptor->size ); |
1037 | | } |
1038 | | #endif |
1039 | 37 | number_of_data_directories_entries--; |
1040 | 37 | } |
1041 | 505 | if( number_of_data_directories_entries > 0 ) |
1042 | 33 | { |
1043 | 33 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_ADDRESS_TABLE ] ); |
1044 | | |
1045 | 33 | byte_stream_copy_to_uint32_little_endian( |
1046 | 33 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_rva, |
1047 | 33 | data_directory_descriptor->virtual_address ); |
1048 | | |
1049 | 33 | byte_stream_copy_to_uint32_little_endian( |
1050 | 33 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_size, |
1051 | 33 | data_directory_descriptor->size ); |
1052 | | |
1053 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1054 | | if( libcnotify_verbose != 0 ) |
1055 | | { |
1056 | | libcnotify_printf( |
1057 | | "%s: import address table RVA\t\t: 0x%08" PRIx32 "\n", |
1058 | | function, |
1059 | | data_directory_descriptor->virtual_address ); |
1060 | | |
1061 | | libcnotify_printf( |
1062 | | "%s: import address table size\t: %" PRIu32 "\n", |
1063 | | function, |
1064 | | data_directory_descriptor->size ); |
1065 | | } |
1066 | | #endif |
1067 | 33 | number_of_data_directories_entries--; |
1068 | 33 | } |
1069 | 505 | if( number_of_data_directories_entries > 0 ) |
1070 | 30 | { |
1071 | 30 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DELAY_IMPORT_DESCRIPTOR ] ); |
1072 | | |
1073 | 30 | byte_stream_copy_to_uint32_little_endian( |
1074 | 30 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_rva, |
1075 | 30 | data_directory_descriptor->virtual_address ); |
1076 | | |
1077 | 30 | byte_stream_copy_to_uint32_little_endian( |
1078 | 30 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_size, |
1079 | 30 | data_directory_descriptor->size ); |
1080 | | |
1081 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1082 | | if( libcnotify_verbose != 0 ) |
1083 | | { |
1084 | | libcnotify_printf( |
1085 | | "%s: delay import descriptor RVA\t: 0x%08" PRIx32 "\n", |
1086 | | function, |
1087 | | data_directory_descriptor->virtual_address ); |
1088 | | |
1089 | | libcnotify_printf( |
1090 | | "%s: delay import descriptor size\t: %" PRIu32 "\n", |
1091 | | function, |
1092 | | data_directory_descriptor->size ); |
1093 | | } |
1094 | | #endif |
1095 | 30 | number_of_data_directories_entries--; |
1096 | 30 | } |
1097 | 505 | if( number_of_data_directories_entries > 0 ) |
1098 | 27 | { |
1099 | 27 | data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_COM_PLUS_RUNTIME_HEADER ] ); |
1100 | | |
1101 | 27 | byte_stream_copy_to_uint32_little_endian( |
1102 | 27 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_rva, |
1103 | 27 | data_directory_descriptor->virtual_address ); |
1104 | | |
1105 | 27 | byte_stream_copy_to_uint32_little_endian( |
1106 | 27 | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_size, |
1107 | 27 | data_directory_descriptor->size ); |
1108 | | |
1109 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1110 | | if( libcnotify_verbose != 0 ) |
1111 | | { |
1112 | | libcnotify_printf( |
1113 | | "%s: COM+ runtime header RVA\t\t: 0x%08" PRIx32 "\n", |
1114 | | function, |
1115 | | data_directory_descriptor->virtual_address ); |
1116 | | |
1117 | | libcnotify_printf( |
1118 | | "%s: COM+ runtime header size\t\t: 0x%08" PRIx32 "\n", |
1119 | | function, |
1120 | | data_directory_descriptor->size ); |
1121 | | } |
1122 | | #endif |
1123 | 27 | number_of_data_directories_entries--; |
1124 | 27 | } |
1125 | 505 | if( number_of_data_directories_entries > 0 ) |
1126 | 14 | { |
1127 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1128 | | if( libcnotify_verbose != 0 ) |
1129 | | { |
1130 | | byte_stream_copy_to_uint64_little_endian( |
1131 | | ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->unknown4, |
1132 | | value_64bit ); |
1133 | | libcnotify_printf( |
1134 | | "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n", |
1135 | | function, |
1136 | | value_64bit ); |
1137 | | |
1138 | | libcnotify_printf( |
1139 | | "\n" ); |
1140 | | } |
1141 | | #endif |
1142 | 14 | number_of_data_directories_entries--; |
1143 | 14 | } |
1144 | 505 | return( 1 ); |
1145 | 510 | } |
1146 | | |
1147 | | /* Reads the COFF optional header from a Basic File IO (bfio) handle |
1148 | | * Returns 1 if successful or -1 on error |
1149 | | */ |
1150 | | int libexe_coff_optional_header_read_file_io_handle( |
1151 | | libexe_coff_optional_header_t *coff_optional_header, |
1152 | | libbfio_handle_t *file_io_handle, |
1153 | | off64_t file_offset, |
1154 | | uint16_t optional_header_size, |
1155 | | libcerror_error_t **error ) |
1156 | 607 | { |
1157 | 607 | uint8_t *data = NULL; |
1158 | 607 | static char *function = "libexe_coff_optional_header_read_file_io_handle"; |
1159 | 607 | ssize_t read_count = 0; |
1160 | | |
1161 | 607 | if( optional_header_size == 0 ) |
1162 | 0 | { |
1163 | 0 | libcerror_error_set( |
1164 | 0 | error, |
1165 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1166 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
1167 | 0 | "%s: invalid optional header size value out of bounds.", |
1168 | 0 | function ); |
1169 | |
|
1170 | 0 | return( -1 ); |
1171 | 0 | } |
1172 | 607 | if( optional_header_size == 0 ) |
1173 | 0 | { |
1174 | 0 | libcerror_error_set( |
1175 | 0 | error, |
1176 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1177 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
1178 | 0 | "%s: invalid optional header size value out of bounds.", |
1179 | 0 | function ); |
1180 | |
|
1181 | 0 | return( -1 ); |
1182 | 0 | } |
1183 | 607 | data = (uint8_t *) memory_allocate( |
1184 | 607 | sizeof( uint8_t ) * optional_header_size ); |
1185 | | |
1186 | 607 | if( data == NULL ) |
1187 | 0 | { |
1188 | 0 | libcerror_error_set( |
1189 | 0 | error, |
1190 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
1191 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
1192 | 0 | "%s: unable to create COFF optional header data.", |
1193 | 0 | function ); |
1194 | |
|
1195 | 0 | goto on_error; |
1196 | 0 | } |
1197 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1198 | | if( libcnotify_verbose != 0 ) |
1199 | | { |
1200 | | libcnotify_printf( |
1201 | | "%s: reading COFF optional header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
1202 | | function, |
1203 | | file_offset, |
1204 | | file_offset ); |
1205 | | } |
1206 | | #endif |
1207 | 607 | read_count = libbfio_handle_read_buffer_at_offset( |
1208 | 607 | file_io_handle, |
1209 | 607 | data, |
1210 | 607 | (size_t) optional_header_size, |
1211 | 607 | file_offset, |
1212 | 607 | error ); |
1213 | | |
1214 | 607 | if( read_count != (ssize_t) optional_header_size ) |
1215 | 17 | { |
1216 | 17 | libcerror_error_set( |
1217 | 17 | error, |
1218 | 17 | LIBCERROR_ERROR_DOMAIN_IO, |
1219 | 17 | LIBCERROR_IO_ERROR_READ_FAILED, |
1220 | 17 | "%s: unable to read COFF optional header data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
1221 | 17 | function, |
1222 | 17 | file_offset, |
1223 | 17 | file_offset ); |
1224 | | |
1225 | 17 | goto on_error; |
1226 | 17 | } |
1227 | 590 | if( libexe_coff_optional_header_read_data( |
1228 | 590 | coff_optional_header, |
1229 | 590 | data, |
1230 | 590 | (size_t) optional_header_size, |
1231 | 590 | error ) != 1 ) |
1232 | 85 | { |
1233 | 85 | libcerror_error_set( |
1234 | 85 | error, |
1235 | 85 | LIBCERROR_ERROR_DOMAIN_IO, |
1236 | 85 | LIBCERROR_IO_ERROR_READ_FAILED, |
1237 | 85 | "%s: unable to read COFF optional header at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
1238 | 85 | function, |
1239 | 85 | file_offset, |
1240 | 85 | file_offset ); |
1241 | | |
1242 | 85 | goto on_error; |
1243 | 85 | } |
1244 | 505 | memory_free( |
1245 | 505 | data ); |
1246 | | |
1247 | 505 | return( 1 ); |
1248 | | |
1249 | 102 | on_error: |
1250 | 102 | if( data != NULL ) |
1251 | 102 | { |
1252 | 102 | memory_free( |
1253 | 102 | data ); |
1254 | 102 | } |
1255 | 102 | return( -1 ); |
1256 | 590 | } |
1257 | | |