1 /*
2 * LE header functions
3 *
4 * Copyright (C) 2011-2021, 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_le_header.h"
28 #include "libexe_libcerror.h"
29 #include "libexe_libcnotify.h"
30
31 #include "exe_le_header.h"
32
33 /* Creates a LE header
34 * Make sure the value le_header is referencing, is set to NULL
35 * Returns 1 if successful or -1 on error
36 */
libexe_le_header_initialize(libexe_le_header_t ** le_header,libcerror_error_t ** error)37 int libexe_le_header_initialize(
38 libexe_le_header_t **le_header,
39 libcerror_error_t **error )
40 {
41 static char *function = "libexe_le_header_initialize";
42
43 if( le_header == NULL )
44 {
45 libcerror_error_set(
46 error,
47 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49 "%s: invalid LE header.",
50 function );
51
52 return( -1 );
53 }
54 if( *le_header != NULL )
55 {
56 libcerror_error_set(
57 error,
58 LIBCERROR_ERROR_DOMAIN_RUNTIME,
59 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
60 "%s: invalid LE header value already set.",
61 function );
62
63 return( -1 );
64 }
65 *le_header = memory_allocate_structure(
66 libexe_le_header_t );
67
68 if( *le_header == NULL )
69 {
70 libcerror_error_set(
71 error,
72 LIBCERROR_ERROR_DOMAIN_MEMORY,
73 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
74 "%s: unable to create LE header.",
75 function );
76
77 goto on_error;
78 }
79 if( memory_set(
80 *le_header,
81 0,
82 sizeof( libexe_le_header_t ) ) == NULL )
83 {
84 libcerror_error_set(
85 error,
86 LIBCERROR_ERROR_DOMAIN_MEMORY,
87 LIBCERROR_MEMORY_ERROR_SET_FAILED,
88 "%s: unable to clear file.",
89 function );
90
91 goto on_error;
92 }
93 return( 1 );
94
95 on_error:
96 if( *le_header != NULL )
97 {
98 memory_free(
99 *le_header );
100
101 *le_header = NULL;
102 }
103 return( -1 );
104 }
105
106 /* Frees a LE header
107 * Returns 1 if successful or -1 on error
108 */
libexe_le_header_free(libexe_le_header_t ** le_header,libcerror_error_t ** error)109 int libexe_le_header_free(
110 libexe_le_header_t **le_header,
111 libcerror_error_t **error )
112 {
113 static char *function = "libexe_le_header_free";
114
115 if( le_header == NULL )
116 {
117 libcerror_error_set(
118 error,
119 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
120 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
121 "%s: invalid LE header.",
122 function );
123
124 return( -1 );
125 }
126 if( *le_header != NULL )
127 {
128 memory_free(
129 *le_header );
130
131 *le_header = NULL;
132 }
133 return( 1 );
134 }
135
136 /* Reads the LE header
137 * Returns 1 if successful or -1 on error
138 */
libexe_le_header_read_data(libexe_le_header_t * le_header,const uint8_t * data,size_t data_size,libcerror_error_t ** error)139 int libexe_le_header_read_data(
140 libexe_le_header_t *le_header,
141 const uint8_t *data,
142 size_t data_size,
143 libcerror_error_t **error )
144 {
145 static char *function = "libexe_le_header_read_data";
146
147 if( le_header == NULL )
148 {
149 libcerror_error_set(
150 error,
151 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
152 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
153 "%s: invalid LE header.",
154 function );
155
156 return( -1 );
157 }
158 if( data == NULL )
159 {
160 libcerror_error_set(
161 error,
162 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164 "%s: invalid data.",
165 function );
166
167 return( -1 );
168 }
169 if( data_size < sizeof( exe_le_header_t ) )
170 {
171 libcerror_error_set(
172 error,
173 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
175 "%s: invalid data size value too small.",
176 function );
177
178 return( -1 );
179 }
180 if( data_size > (size_t) SSIZE_MAX )
181 {
182 libcerror_error_set(
183 error,
184 LIBCERROR_ERROR_DOMAIN_RUNTIME,
185 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
186 "%s: invalid data size value exceeds maximum.",
187 function );
188
189 return( -1 );
190 }
191 #if defined( HAVE_DEBUG_OUTPUT )
192 if( libcnotify_verbose != 0 )
193 {
194 libcnotify_printf(
195 "%s: LE header:\n",
196 function );
197 libcnotify_print_data(
198 data,
199 sizeof( exe_le_header_t ),
200 0 );
201 }
202 #endif
203 if( memory_compare(
204 ( (exe_le_header_t *) data )->signature,
205 EXE_LE_SIGNATURE,
206 2 ) != 0 )
207 {
208 libcerror_error_set(
209 error,
210 LIBCERROR_ERROR_DOMAIN_RUNTIME,
211 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
212 "%s: invalid signature.",
213 function );
214
215 return( -1 );
216 }
217 #if defined( HAVE_DEBUG_OUTPUT )
218 if( libcnotify_verbose != 0 )
219 {
220 libcnotify_printf(
221 "%s: signature\t\t\t\t: %c%c\n",
222 function,
223 ( (exe_le_header_t *) data )->signature[ 0 ],
224 ( (exe_le_header_t *) data )->signature[ 1 ] );
225 /* TODO */
226
227 libcnotify_printf(
228 "\n" );
229 }
230 #endif
231 return( 1 );
232 }
233
234 /* Reads the LE header from a Basic File IO (bfio) handle
235 * Returns 1 if successful or -1 on error
236 */
libexe_le_header_read_file_io_handle(libexe_le_header_t * le_header,libbfio_handle_t * file_io_handle,off64_t file_offset,libcerror_error_t ** error)237 int libexe_le_header_read_file_io_handle(
238 libexe_le_header_t *le_header,
239 libbfio_handle_t *file_io_handle,
240 off64_t file_offset,
241 libcerror_error_t **error )
242 {
243 uint8_t data[ sizeof( exe_le_header_t ) ];
244
245 static char *function = "libexe_le_header_read_file_io_handle";
246 ssize_t read_count = 0;
247
248 #if defined( HAVE_DEBUG_OUTPUT )
249 if( libcnotify_verbose != 0 )
250 {
251 libcnotify_printf(
252 "%s: reading LE header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
253 function,
254 file_offset,
255 file_offset );
256 }
257 #endif
258 read_count = libbfio_handle_read_buffer_at_offset(
259 file_io_handle,
260 data,
261 sizeof( exe_le_header_t ),
262 file_offset,
263 error );
264
265 if( read_count != (ssize_t) sizeof( exe_le_header_t ) )
266 {
267 libcerror_error_set(
268 error,
269 LIBCERROR_ERROR_DOMAIN_IO,
270 LIBCERROR_IO_ERROR_READ_FAILED,
271 "%s: unable to read LE header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
272 function,
273 file_offset,
274 file_offset );
275
276 return( -1 );
277 }
278 if( libexe_le_header_read_data(
279 le_header,
280 data,
281 sizeof( exe_le_header_t ),
282 error ) != 1 )
283 {
284 libcerror_error_set(
285 error,
286 LIBCERROR_ERROR_DOMAIN_IO,
287 LIBCERROR_IO_ERROR_READ_FAILED,
288 "%s: unable to read LE header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
289 function,
290 file_offset,
291 file_offset );
292
293 return( -1 );
294 }
295 return( 1 );
296 }
297
298