1 // Scalpel Copyright (C) 2005-11 by Golden G. Richard III and
2 // 2007-11 by Vico Marziale.
3 // Written by Golden G. Richard III and Vico Marziale.
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 // Thanks to Kris Kendall, Jesse Kornblum, et al for their work
21 // on Foremost. Foremost 0.69 was used as the starting point for
22 // Scalpel, in 2005.
23
24 #include "scalpel.h"
25
26 // get # of seconds between two specified times
27 #if defined(_WIN32)
elapsed(LARGE_INTEGER A,LARGE_INTEGER B)28 inline double elapsed(LARGE_INTEGER A, LARGE_INTEGER B) {
29 LARGE_INTEGER freq;
30 QueryPerformanceFrequency(&freq);
31 return fabs(((double)A.QuadPart - (double)B.QuadPart) /
32 (double)freq.QuadPart);
33 }
34 #else
elapsed(struct timeval A,struct timeval B)35 double elapsed(struct timeval A, struct timeval B) {
36 return fabs(A.tv_sec - B.tv_sec) + fabs(A.tv_usec - B.tv_usec) / 1000000;
37 }
38 #endif
39
40 // determine if a string begins and ends with '/' characters
isRegularExpression(char * s)41 int isRegularExpression(char *s) {
42 return (s && s[0] && s[0] == '/' && s[strlen(s) - 1] == '/');
43 }
44
45
46 void
checkMemoryAllocation(struct scalpelState * state,void * ptr,int line,const char * file,const char * structure)47 checkMemoryAllocation(struct scalpelState *state, void *ptr, int line,
48 const char *file, const char *structure) {
49 if(ptr) {
50 return;
51 }
52 else {
53 fprintf(stderr, "** MEMORY ALLOCATION FAILURE **\n");
54 fprintf(stderr,
55 "ERROR: Memory exhausted at line %d in file %s. Scalpel was \n",
56 line, file);
57 fprintf(stderr,
58 "allocating memory for %s when this condition occurred.\n",
59 structure);
60
61 fprintf(state->auditFile,
62 "ERROR: Memory exhausted at line %d in file %s. Scalpel was \n",
63 line, file);
64 fprintf(state->auditFile,
65 "allocating memory for %s when this condition occurred.\n",
66 structure);
67
68 handleError(state, SCALPEL_GENERAL_ABORT); // fatal
69 }
70 }
71
72
73 #ifndef __GLIBC__
setProgramName(char * s)74 void setProgramName(char *s) {
75 char *fn = (char *)malloc(sizeof(char) * PATH_MAX);
76 if(realpath(s, fn) == NULL) {
77 __scalpel__progname = strdup("scalpel");
78 return;
79 }
80
81 __scalpel__progname = basename(fn);
82 }
83
84 #endif /* ifndef __GLIBC__ */
85
86
87 // write entry to both the screen and the audit file (if possible)
scalpelLog(struct scalpelState * state,const char * format,...)88 void scalpelLog(struct scalpelState *state, const char *format, ...) {
89
90 va_list argp;
91
92 va_start(argp, format);
93 vfprintf(stderr, format, argp);
94 va_end(argp);
95
96 va_start(argp, format);
97 if(state->auditFile) {
98 vfprintf(state->auditFile, format, argp);
99 }
100 va_end(argp);
101 }
102
103 // determine if two characters match, with optional case
104 // insensitivity. If a is the Scalpel wildcard character,
105 // then a and b will always match.
charactersMatch(char a,char b,int caseSensitive)106 int charactersMatch(char a, char b, int caseSensitive) {
107
108 if(a == wildcard || a == b) {
109 return 1;
110 }
111 if(caseSensitive || (a < 'A' || a > 'z' || b < 'A' || b > 'z')) {
112 return 0;
113 }
114
115 /* This line is equivalent to (abs(a-b)) == 'a' - 'A' */
116 return (abs(a - b) == 32);
117 }
118
119
120 // memwildcardcmp is a memcmp() clone, except that single
121 // character wildcards are supported. The default wildcard character is '?',
122 // but this can be redefined in the configuration file. A wildcard in s1 will
123 // match any single character in s2.
memwildcardcmp(const void * s1,const void * s2,size_t n,int caseSensitive)124 int memwildcardcmp(const void *s1, const void *s2, size_t n, int caseSensitive) {
125 if(n != 0) {
126 register const unsigned char *p1 = (const unsigned char *)s1,
127 *p2 = (const unsigned char *)s2;
128 do {
129 if(!charactersMatch(*p1++, *p2++, caseSensitive)) {
130 return (*--p1 - *--p2);
131 }
132 }
133 while (--n != 0);
134 }
135 return 0;
136 }
137
138
139 // initialize Boyer-Moore "jump table" for search. Dependence
140 // on search type (e.g., FORWARD, REVERSE, etc.) from Foremost
141 // has been removed, because Scalpel always performs searches across
142 // a buffer in a forward direction.
143 void
init_bm_table(char * needle,size_t table[UCHAR_MAX+1],size_t len,int casesensitive)144 init_bm_table(char *needle, size_t table[UCHAR_MAX + 1],
145 size_t len, int casesensitive) {
146
147 size_t i = 0, j = 0, currentindex = 0;
148
149 for(i = 0; i <= UCHAR_MAX; i++) {
150 table[i] = len;
151 }
152
153 for(i = 0; i < len; i++) {
154 currentindex = len - i - 1; //Count from the back of string
155 //No skip entry can advance us past the last wildcard in the string
156 if(needle[i] == wildcard) {
157 for(j = 0; j <= UCHAR_MAX; j++) {
158 table[j] = currentindex;
159 }
160 }
161 table[(unsigned char)needle[i]] = currentindex;
162 if(!casesensitive && needle[i] > 0) {
163 table[tolower(needle[i])] = currentindex;
164 table[toupper(needle[i])] = currentindex;
165 }
166 }
167 }
168
169 #ifdef USE_SIMPLE_STRING_SEARCH
170
171 // Perform a simple string search, supporting wildcards,
172 // case-insensitive searches, and specifiable start locations in the buffer.
173 // The parameter 'table' is ignored.
bm_needleinhaystack_skipnchars(char * needle,size_t needle_len,char * haystack,size_t haystack_len,size_t table[UCHAR_MAX+1],int casesensitive,int start_pos)174 char *bm_needleinhaystack_skipnchars(char *needle, size_t needle_len,
175 char *haystack, size_t haystack_len,
176 size_t table[UCHAR_MAX + 1],
177 int casesensitive, int start_pos) {
178
179 register int i, j, go;
180
181 if(needle_len == 0) {
182 return haystack;
183 }
184
185 for(i = start_pos; i < haystack_len; i++) {
186 go = 1;
187 j = 0;
188 while (go) {
189 go = (i + j) < haystack_len && j < needle_len &&
190 charactersMatch(needle[j], haystack[i + j], casesensitive);
191 j++;
192 }
193
194 if(j > needle_len) {
195 return haystack + i;
196 }
197 }
198
199 return NULL;
200
201 }
202
203 #endif
204
205
206
207 #ifdef USE_FAST_STRING_SEARCH
208
209 // Perform a modified Boyer-Moore string search, supporting wildcards,
210 // case-insensitive searches, and specifiable start locations in the buffer.
211 // Dependence on search type (e.g., FORWARD, REVERSe, etc.) from Foremost has
212 // been removed, because Scalpel always performs forward searching.
bm_needleinhaystack_skipnchars(char * needle,size_t needle_len,char * haystack,size_t haystack_len,size_t table[UCHAR_MAX+1],int casesensitive,int start_pos)213 char *bm_needleinhaystack_skipnchars(char *needle, size_t needle_len,
214 char *haystack, size_t haystack_len,
215 size_t table[UCHAR_MAX + 1],
216 int casesensitive, int start_pos) {
217
218 register size_t shift = 0;
219 register size_t pos = start_pos;
220 char *here;
221
222 if(needle_len == 0) {
223 return haystack;
224 }
225
226 while (pos < haystack_len) {
227 while (pos < haystack_len
228 && (shift = table[(unsigned char)haystack[pos]]) > 0) {
229 pos += shift;
230 }
231 if(0 == shift) {
232 if(0 ==
233 memwildcardcmp(needle, here =
234 (char *)&haystack[pos - needle_len + 1],
235 needle_len, casesensitive)) {
236 return (here);
237 }
238 else {
239 pos++;
240 }
241 }
242 }
243 return NULL;
244 }
245
246 #endif
247
248
bm_needleinhaystack(char * needle,size_t needle_len,char * haystack,size_t haystack_len,size_t table[UCHAR_MAX+1],int casesensitive)249 char *bm_needleinhaystack(char *needle, size_t needle_len,
250 char *haystack, size_t haystack_len,
251 size_t table[UCHAR_MAX + 1], int casesensitive) {
252
253 return bm_needleinhaystack_skipnchars(needle,
254 needle_len,
255 haystack,
256 haystack_len,
257 table, casesensitive, needle_len - 1);
258 }
259
260
261
262 // find longest header OR footer. Headers or footers which are
263 // regular expressions are assigned LARGEST_REGEXP_OVERLAP lengths, to
264 // allow for regular expressions spanning SIZE_OF_BUFFER-sized chunks
265 // of the disk image.
findLongestNeedle(struct SearchSpecLine * SearchSpec)266 int findLongestNeedle(struct SearchSpecLine *SearchSpec) {
267 int longest = 0;
268 int i = 0;
269 int lenb, lene;
270 for(i = 0; SearchSpec[i].suffix != NULL; i++) {
271 lenb =
272 SearchSpec[i].beginisRE ? LARGEST_REGEXP_OVERLAP : SearchSpec[i].
273 beginlength;
274 lene =
275 SearchSpec[i].endisRE ? LARGEST_REGEXP_OVERLAP : SearchSpec[i].endlength;
276 if(lenb > longest) {
277 longest = lenb;
278 }
279 if(lene > longest) {
280 longest = lene;
281 }
282 }
283 return longest;
284 }
285
286
287 // do a regular expression search using the Tre regular expression
288 // library. The needle is a previously compiled regular expression
289 // (via Tre regcomp()). The caller must free the memory associated
290 // with the returned regmatch_t structure.
re_needleinhaystack(regex_t * needle,char * haystack,size_t haystack_len)291 regmatch_t *re_needleinhaystack(regex_t * needle, char *haystack,
292 size_t haystack_len) {
293
294 regmatch_t *match = (regmatch_t *) malloc(sizeof(regmatch_t));
295
296
297 // LMIII temp fix till working with g++
298 if(!regnexec(needle, haystack, (size_t) haystack_len, (size_t) 1, match, 0)) {
299 // match
300 return match;
301 }
302 else {
303 // no match
304 return NULL;
305 }
306 }
307
308
309 // decode strings with embedded escape sequences and return the total length of the
310 // translated string.
311
translate(char * str)312 int translate(char *str) {
313 char next;
314 char *rd = str, *wr = str, *bad;
315 char temp[1 + 3 + 1];
316 char ch;
317
318 if(!*rd) { //If it's a null string just return
319 return 0;
320 }
321
322 while (*rd) {
323 // Is it an escaped character?
324 if(*rd == '\\') {
325 rd++;
326 switch (*rd) {
327 case '\\':
328 rd++;
329 *(wr++) = '\\';
330 break;
331 case 'a':
332 rd++;
333 *(wr++) = '\a';
334 break;
335 case 's':
336 rd++;
337 *(wr++) = ' ';
338 break;
339 case 'n':
340 rd++;
341 *(wr++) = '\n';
342 break;
343 case 'r':
344 rd++;
345 *(wr++) = '\r';
346 break;
347 case 't':
348 rd++;
349 *(wr++) = '\t';
350 break;
351 case 'v':
352 rd++;
353 *(wr++) = '\v';
354 break;
355 // Hexadecimal/Octal values are treated in one place using strtoul()
356 case 'x':
357 case '0':
358 case '1':
359 case '2':
360 case '3':
361 next = *(rd + 1);
362 if(next < 48 || (57 < next && next < 65) ||
363 (70 < next && next < 97) || next > 102)
364 break; //break if not a digit or a-f, A-F
365 next = *(rd + 2);
366 if(next < 48 || (57 < next && next < 65) ||
367 (70 < next && next < 97) || next > 102)
368 break; //break if not a digit or a-f, A-F
369
370 temp[0] = '0';
371 bad = temp;
372 strncpy(temp + 1, rd, 3);
373 temp[4] = '\0';
374 ch = strtoul(temp, &bad, 0);
375 if(*bad == '\0') {
376 *(wr++) = ch;
377 rd += 3;
378 } // else INVALID CHARACTER IN INPUT ('\\' followed by *rd)
379 break;
380 default: // INVALID CHARACTER IN INPUT (*rd)
381 *(wr++) = '\\';
382 break;
383 }
384 }
385 // just copy un-escaped characters
386 else {
387 *(wr++) = *(rd++);
388 }
389 }
390 *wr = '\0'; // null termination
391 return wr - str;
392 }
393
394 // skip leading whitespace
skipWhiteSpace(char * str)395 char *skipWhiteSpace(char *str) {
396 while (isspace(str[0])) {
397 str++;
398 }
399 return str;
400 }
401
402 // describe Scalpel error conditions. Some errors are fatal, while
403 // others are advisory.
handleError(struct scalpelState * state,int error)404 void handleError(struct scalpelState *state, int error) {
405
406 switch (error) {
407
408 case SCALPEL_ERROR_PTHREAD_FAILURE:
409 // fatal
410 scalpelLog(state,
411 "Scalpel was unable to create threads and will abort.\n");
412 closeAuditFile(state->auditFile);
413 exit(-1);
414 break;
415
416 case SCALPEL_ERROR_FILE_OPEN:
417 // non-fatal
418 if (state->imagefile == 0 || *(state->imagefile) == '\0') {
419 scalpelLog(state, "Scalpel was unable to open the image file: <blank>....\n"
420 "Skipping...\n");
421 }
422 else {
423 scalpelLog(state, "Scalpel was unable to open the image file: %s...%s\n"
424 "Skipping...\n", state->imagefile, strerror(errno));
425 }
426 break;
427 case SCALPEL_ERROR_FILE_TOO_SMALL:
428 // non-fatal
429 scalpelLog(state,
430 "The image file %s is smaller than the longest header/footer and cannot be processed.\n"
431 "Skipping...\n", state->imagefile);
432 break;
433
434 case SCALPEL_ERROR_FILE_READ:
435 // non-fatal
436 scalpelLog(state, "Scalpel was unable to read the image file: %s\n"
437 "Skipping...\n", state->imagefile);
438 break;
439
440 case SCALPEL_ERROR_FATAL_READ:
441 // fatal
442 scalpelLog(state,
443 "Scalpel was unable to read a needed file and will abort.\n");
444 closeAuditFile(state->auditFile);
445 exit(-1);
446 break;
447
448 case SCALPEL_ERROR_NONEMPTY_DIRECTORY:
449 // fatal
450 fprintf(stderr,
451 "Scalpel will write only to empty output directories to avoid\n");
452 fprintf(stderr, "mixing the output from multiple carving operations.\n");
453 fprintf(stderr,
454 "Please specify a different output directory or delete the specified\noutput directory.\n");
455 closeAuditFile(state->auditFile);
456 exit(-1);
457 break;
458
459 case SCALPEL_ERROR_FILE_WRITE:
460 // fatal--unable to write files, which may mean that disk space is exhausted.
461 fprintf(stderr,
462 "Scalpel was unable to write output files and will abort.\n");
463 fprintf(stderr,
464 "This error generally indicates that disk space is exhausted.\n");
465 closeAuditFile(state->auditFile);
466 exit(-1);
467 break;
468
469 case SCALPEL_ERROR_NO_SEARCH_SPEC:
470 // fatal, configuration file didn't specify anything to carve
471 scalpelLog(state,
472 "ERROR: The configuration file didn't specify any file types to carve.\n");
473 scalpelLog(state,
474 "(If you're using the default configuration file, you'll have to\n");
475 scalpelLog(state, "uncomment some of the file types.)\n");
476 closeAuditFile(state->auditFile);
477 exit(-1);
478 break;
479
480 case SCALPEL_GENERAL_ABORT:
481 // fatal
482 scalpelLog(state, "Scalpel will abort.\n");
483 closeAuditFile(state->auditFile);
484 exit(-1);
485 break;
486
487 default:
488 // fatal
489 closeAuditFile(state->auditFile);
490 exit(-1);
491 }
492 }
493
494
setttywidth(void)495 void setttywidth(void) {
496 #if defined (_WIN32)
497 CONSOLE_SCREEN_BUFFER_INFO csbi;
498 HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
499 if(!GetConsoleScreenBufferInfo(hConsole, &csbi)) {
500 ttywidth = 80;
501 }
502 else {
503 ttywidth = csbi.dwSize.X;
504 }
505 #else
506 //#if defined(__BSD)
507 // ttywidth = 80;
508 //#else
509 struct winsize winsize;
510 if(ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) {
511 ttywidth = winsize.ws_col;
512 }
513 else {
514 // 80 is a reasonable default
515 ttywidth = 80;
516 }
517 //#endif
518 #endif
519 }
520
521
skipInFile(struct scalpelState * state,FILE * infile)522 int skipInFile(struct scalpelState *state, FILE * infile) {
523
524 int retries = 0;
525 while (TRUE) {
526 if((fseeko(infile, state->skip, SEEK_SET))) {
527
528 #ifdef _WIN32
529 fprintf(stderr,
530 "ERROR: Couldn't skip %I64u bytes at the start of image file %s\n",
531 state->skip, state->imagefile);
532 #else
533 fprintf(stderr,
534 "ERROR: Couldn't skip %lld bytes at the start of image file %s\n",
535 state->skip, state->imagefile);
536 #endif
537
538 if(retries++ > 3) {
539 fprintf(stderr, "Sorry, maximum retries exceeded...\n");
540 return FALSE;
541 }
542 else {
543 fprintf(stderr, "Waiting to try again... \n");
544 sleep(3);
545 }
546 }
547 else {
548 #ifdef _WIN32
549 fprintf(stderr, "Skipped the first %I64u bytes of %s...\n",
550 state->skip, state->imagefile);
551 #else
552 fprintf(stderr, "Skipped the first %lld bytes of %s...\n",
553 state->skip, state->imagefile);
554 #endif
555
556
557 return TRUE;
558 }
559 }
560 }
561