1 
2 	 /* MD5DEEP - helpers.c
3  *
4  * By Jesse Kornblum
5  *
6  * This is a work of the US Government. In accordance with 17 USC 105,
7  * copyright protection is not available for any work of the US Government.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  */
14 
15 #include "main.h"
16 
17 /* Removes any newlines at the end of the string buf.
18    Works for both *nix and Windows styles of newlines.
19    Returns the new length of the string. */
chop(char * buf)20 unsigned int chop (char *buf)
21 	{
22 
23 	/* Windows newlines are 0x0d 0x0a, *nix are 0x0a */
24 	unsigned int	len = strlen(buf);
25 	if (buf[len - 1] == 0x0a)
26 		{
27 		if (buf[len - 2] == 0x0d)
28 			{
29 			buf[len - 2] = buf[len - 1];
30 			}
31 		buf[len - 1] = buf[len];
32 		}
33 	return strlen(buf);
34 	}
35 
units(unsigned int c)36 char *units(unsigned int c)
37 {
38 	switch (c)
39 		{
40 		case 0:		return "B";
41 		case 1:		return "KB";
42 		case 2:		return "MB";
43 		case 3:		return "GB";
44 		case 4:		return "TB";
45 		case 5:		return "PB";
46 		case 6:		return "EB";
47 		/* Steinbach's Guideline for Systems Programming:
48        Never test for an error condition you don't know how to handle.
49 
50        Granted, given that no existing system can handle anything
51        more than 18 exabytes, this shouldn't be an issue. But how do we
52        communicate that 'this shouldn't happen' to the user? */
53 		default:	return "??";
54 		}
55 }
56 
human_readable(off_t size,char * buffer)57 char *human_readable(off_t size, char *buffer)
58 {
59 	unsigned int	count = 0;
60 	while (size > 1024)
61 		{
62 		size /= 1024;
63 		++count;
64 		}
65 
66 	/* The size will be, at most, 1023, and the units will be
67      two characters no matter what. Thus, the maximum length of
68      this string is six characters. e.g. strlen("1023 EB") = 6 */
69 	if (sizeof(off_t) == 4)
70 		{
71 		snprintf(buffer, 8, "%u %s", (unsigned int)size, units(count));
72 		}
73 	else if (sizeof(off_t) == 8)
74 		{
75 		snprintf(buffer, 8, "%llu %s", (u_int64_t) size, units(count));
76 		}
77 
78 	return buffer;
79 }
80 
current_time(void)81 char *current_time(void)
82 {
83 	time_t	now = time(NULL);
84 	char	*ascii_time = ctime(&now);
85 	chop(ascii_time);
86 	return ascii_time;
87 }
88 
89 /* Shift the contents of a string so that the values after 'new_start'
90    will now begin at location 'start' */
shift_string(char * fn,int start,int new_start)91 void shift_string(char *fn, int start, int new_start)
92 {
93 	if (start < 0 || start > strlen(fn) || new_start < 0 || new_start < start)
94 		return;
95 
96 	while (new_start < strlen(fn))
97 		{
98 		fn[start] = fn[new_start];
99 		new_start++;
100 		start++;
101 		}
102 
103 	fn[start] = 0;
104 }
105 
make_magic(void)106 void make_magic(void)
107 {
108 	printf("%s%s",
109 		   "\x53\x41\x4E\x20\x44\x49\x4D\x41\x53\x20\x48\x49\x47\x48\x20\x53\x43\x48\x4F\x4F\x4C\x20\x46\x4F\x4F\x54\x42\x41\x4C\x4C\x20\x52\x55\x4C\x45\x53\x21",
110 	   NEWLINE);
111 }
112 
113 #if defined(__UNIX)
114 
115 /* Return the size, in bytes of an open file stream. On error, return 0 */
116 	#if defined(__LINUX)
117 
find_file_size(FILE * f)118 off_t find_file_size(FILE *f)
119 {
120 	off_t		num_sectors = 0;
121 	int			fd = fileno(f);
122 	struct stat sb;
123 
124 	if (fstat(fd, &sb))
125 		{
126 		return 0;
127 		}
128 
129 	if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
130 		return sb.st_size;
131 	else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))
132 		{
133 		if (ioctl(fd, BLKGETSIZE, &num_sectors))
134 		{
135 		#if defined(__DEBUG)
136 			fprintf(stderr, "%s: ioctl call to BLKGETSIZE failed.%s", __progname, NEWLINE);
137 		#endif
138 		}
139 		else
140 			return (num_sectors * 512);
141 		}
142 
143 	return 0;
144 }
145 
146 	#elif defined(__MACOSX)
147 
148 		#include <stdint.h>
149 		#include <sys/ioctl.h>
150 		#include <sys/disk.h>
151 
find_file_size(FILE * f)152 off_t find_file_size(FILE *f)
153 {
154 		#ifdef DEBUG
155 	printf("	FIND MAC file size\n");
156 		#endif
157 	return 0;	/*FIX ME this function causes strange problems on MACOSX, so for now return 0*/
158 	struct stat info;
159 	off_t		total = 0;
160 	off_t		original = ftello(f);
161 	int			ok = TRUE, fd = fileno(f);
162 
163 	/* I'd prefer not to use fstat as it will follow symbolic links. We don't
164      follow symbolic links. That being said, all symbolic links *should*
165      have been caught before we got here. */
166 	fstat(fd, &info);
167 
168 	/* Block devices, like /dev/hda, don't return a normal filesize.
169      If we are working with a block device, we have to ask the operating
170      system to tell us the true size of the device.
171 
172      The following only works on Linux as far as I know. If you know
173      how to port this code to another operating system, please contact
174      the current maintainer of this program! */
175 	if (S_ISBLK(info.st_mode))
176 		{
177 		daddr_t blocksize = 0;
178 		daddr_t blockcount = 0;
179 
180 		/* Get the block size */
181 		if (ioctl(fd, DKIOCGETBLOCKSIZE, blocksize) < 0)
182 			{
183 			ok = FALSE;
184 		#if defined(__DEBUG)
185 			perror("DKIOCGETBLOCKSIZE failed");
186 		#endif
187 			}
188 
189 		/* Get the number of blocks */
190 		if (ok)
191 			{
192 			if (ioctl(fd, DKIOCGETBLOCKCOUNT, blockcount) < 0)
193 			{
194 		#if defined(__DEBUG)
195 				perror("DKIOCGETBLOCKCOUNT failed");
196 		#endif
197 			}
198 			}
199 
200 		total = blocksize * blockcount;
201 
202 		}
203 
204 	else
205 		{
206 
207 		/* I don't know why, but if you don't initialize this value you'll
208        get wildly innacurate results when you try to run this function */
209 		if ((fseeko(f, 0, SEEK_END)))
210 			return 0;
211 		total = ftello(f);
212 		if ((fseeko(f, original, SEEK_SET)))
213 			return 0;
214 		}
215 
216 	return (total - original);
217 }
218 
219 	#else
220 
221 /* This is code for general UNIX systems
222    (e.g. NetBSD, FreeBSD, OpenBSD, etc) */
midpoint(off_t a,off_t b,long blksize)223 static off_t midpoint(off_t a, off_t b, long blksize)
224 {
225 	off_t	aprime = a / blksize;
226 	off_t	bprime = b / blksize;
227 	off_t	c, cprime;
228 
229 	cprime = (bprime - aprime) / 2 + aprime;
230 	c = cprime * blksize;
231 
232 	return c;
233 }
234 
find_dev_size(int fd,int blk_size)235 off_t find_dev_size(int fd, int blk_size)
236 {
237 
238 	off_t	curr = 0, amount = 0;
239 	void	*buf;
240 
241 	if (blk_size == 0)
242 		return 0;
243 
244 	buf = malloc(blk_size);
245 
246 	for (;;)
247 		{
248 		ssize_t nread;
249 
250 		lseek(fd, curr, SEEK_SET);
251 		nread = read(fd, buf, blk_size);
252 		if (nread < blk_size)
253 			{
254 			if (nread <= 0)
255 				{
256 				if (curr == amount)
257 					{
258 					free(buf);
259 					lseek(fd, 0, SEEK_SET);
260 					return amount;
261 					}
262 
263 				curr = midpoint(amount, curr, blk_size);
264 				}
265 			else
266 				{	/* 0 < nread < blk_size */
267 				free(buf);
268 				lseek(fd, 0, SEEK_SET);
269 				return amount + nread;
270 				}
271 			}
272 		else
273 			{
274 			amount = curr + blk_size;
275 			curr = amount * 2;
276 			}
277 		}
278 
279 	free(buf);
280 	lseek(fd, 0, SEEK_SET);
281 	return amount;
282 }
283 
find_file_size(FILE * f)284 off_t find_file_size(FILE *f)
285 {
286 	int			fd = fileno(f);
287 	struct stat sb;
288 	return 0;		/*FIX ME SOLARIS FILE SIZE CAUSES SEG FAULT, for now just return 0*/
289 
290 	if (fstat(fd, &sb))
291 		return 0;
292 
293 	if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
294 		return sb.st_size;
295 	else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))
296 		return find_dev_size(fd, sb.st_blksize);
297 
298 	return 0;
299 }
300 
301 	#endif /* UNIX Flavors */
302 #endif /* ifdef __UNIX */
303 
304 #if defined(__WIN32)
find_file_size(FILE * f)305 off_t find_file_size(FILE *f)
306 {
307 	off_t	total = 0, original = ftello(f);
308 
309 	if ((fseeko(f, 0, SEEK_END)))
310 		return 0;
311 
312 	total = ftello(f);
313 	if ((fseeko(f, original, SEEK_SET)))
314 		return 0;
315 
316 	return total;
317 }
318 
319 #endif /* ifdef __WIN32 */
320 
print_search_specs(f_state * s)321 void print_search_specs(f_state *s)
322 {
323 	int i = 0;
324 	int j = 0;
325 	printf("\nDUMPING BUILTIN SEARCH INFO\n\t");
326 	for (i = 0; i < s->num_builtin; i++)
327 		{
328 
329 		printf("%s:\n\t footer_len:=%d, header_len:=%d, max_len:=%llu ",
330 			   search_spec[i].suffix,
331 			   search_spec[i].footer_len,
332 			   search_spec[i].header_len,
333 			   search_spec[i].max_len);
334 		printf("\n\t header:\t");
335 		printx(search_spec[i].header, 0, search_spec[i].header_len);
336 		printf("\t footer:\t");
337 		printx(search_spec[i].footer, 0, search_spec[i].footer_len);
338 		for (j = 0; j < search_spec[i].num_markers; j++)
339 			{
340 			printf("\tmarker: \t");
341 			printx(search_spec[i].markerlist[j].value, 0, search_spec[i].markerlist[j].len);
342 			}
343 
344 		}
345 
346 }
347 
print_stats(f_state * s)348 void print_stats(f_state *s)
349 {
350 	int i = 0;
351 	audit_msg(s, "\n%d FILES EXTRACTED\n\t", s->fileswritten);
352 	for (i = 0; i < s->num_builtin; i++)
353 		{
354 
355 		if (search_spec[i].found != 0)
356 			{
357 			if (search_spec[i].type == OLE)
358 				search_spec[i].suffix = "ole";
359 			else if (search_spec[i].type == RIFF)
360 				search_spec[i].suffix = "rif";
361 			else if (search_spec[i].type == ZIP)
362 				search_spec[i].suffix = "zip";
363 			audit_msg(s, "%s:= %d", search_spec[i].suffix, search_spec[i].found);
364 			}
365 		}
366 }
367 
charactersMatch(char a,char b,int caseSensitive)368 int charactersMatch(char a, char b, int caseSensitive)
369 {
370 
371 	//if(a==b) return 1;
372 	if (a == wildcard || a == b)
373 		return 1;
374 	if (caseSensitive || (a < 'A' || a > 'z' || b < 'A' || b > 'z'))
375 		return 0;
376 
377 	/* This line is equivalent to (abs(a-b)) == 'a' - 'A' */
378 	return (abs(a - b) == 32);
379 }
380 
memwildcardcmp(const void * s1,const void * s2,size_t n,int caseSensitive)381 int memwildcardcmp(const void *s1, const void *s2, size_t n, int caseSensitive)
382 {
383 	if (n != 0)
384 		{
385 		register const unsigned char	*p1 = s1, *p2 = s2;
386 		do
387 			{
388 			if (!charactersMatch(*p1++, *p2++, caseSensitive))
389 				return (*--p1 -*--p2);
390 			}
391 		while (--n != 0);
392 		}
393 
394 	return (0);
395 }
396 
printx(unsigned char * buf,int start,int end)397 void printx(unsigned char *buf, int start, int end)
398 {
399 	int i = 0;
400 	for (i = start; i < end; i++)
401 		{
402 		printf("%x ", buf[i]);
403 		}
404 
405 	printf("\n");
406 }
407 
reverse_string(char * to,char * from,int startLocation,int endLocation)408 char *reverse_string(char *to, char *from, int startLocation, int endLocation)
409 {
410 	int i = endLocation;
411 	int j = 0;
412 	for (j = startLocation; j < endLocation; j++)
413 		{
414 		i--;
415 		to[j] = from[i];
416 		}
417 
418 	return to;
419 }
420 
htos(unsigned char s[],int endian)421 unsigned short htos(unsigned char s[], int endian)
422 {
423 
424 	unsigned char	*bytes = (unsigned char *)malloc(sizeof(unsigned short) * sizeof(char));
425 	unsigned short	size = 0;
426 	char			temp = 'x';
427 	bytes = memcpy(bytes, s, sizeof(short));
428 
429 	if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
430 		{
431 
432 		//printf("switching the byte order\n");
433 		temp = bytes[0];
434 		bytes[0] = bytes[1];
435 		bytes[1] = temp;
436 
437 		}
438 	else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
439 		{
440 		temp = bytes[0];
441 		bytes[0] = bytes[1];
442 		bytes[1] = temp;
443 		}
444 
445 	size = *((unsigned short *)bytes);
446 	free(bytes);
447 	return size;
448 }
449 
htoi(unsigned char s[],int endian)450 unsigned int htoi(unsigned char s[], int endian)
451 {
452 
453 	int				length = sizeof(int);
454 	unsigned char	*bytes = (unsigned char *)malloc(length * sizeof(char));
455 	unsigned int	size = 0;
456 
457 	bytes = memcpy(bytes, s, length);
458 
459 	if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
460 		{
461 
462 		bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
463 		}
464 	else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
465 		{
466 
467 		bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
468 		}
469 
470 	size = *((unsigned int *)bytes);
471 
472 	free(bytes);
473 	return size;
474 }
475 
htoll(unsigned char s[],int endian)476 u_int64_t htoll(unsigned char s[], int endian)
477 {
478 	int				length = sizeof(u_int64_t);
479 	unsigned char	*bytes = (unsigned char *)malloc(length * sizeof(char));
480 	u_int64_t	size = 0;
481 	bytes = memcpy(bytes, s, length);
482 #ifdef DEBUG
483 	printf("htoll len=%d endian=%d\n",length,endian);
484 #endif
485 	if (endian == FOREMOST_BIG_ENDIAN && BYTE_ORDER == LITTLE_ENDIAN)
486 		{
487 #ifdef DEBUG
488 		printf("reverse0\n");
489 #endif
490 		bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
491 		}
492 	else if (endian == FOREMOST_LITTLE_ENDIAN && BYTE_ORDER == BIG_ENDIAN)
493 		{
494 #ifdef DEBUG
495 	printf("reverse1\n");
496 #endif
497 		bytes = (unsigned char *)reverse_string((char *)bytes, (char *)s, 0, length);
498 		}
499 
500 	size = *((u_int64_t *)bytes);
501 #ifdef DEBUG
502 	printf("htoll size=%llu\n",size);
503 	printx(bytes,0,length);
504 #endif
505 
506 
507 	free(bytes);
508 	return size;
509 }
510 
511 /* display Position: Tell the user how far through the infile we are */
displayPosition(f_state * s,f_info * i,u_int64_t pos)512 int displayPosition(f_state *s, f_info *i, u_int64_t pos)
513 {
514 
515 	int			percentDone = 0;
516 	static int	last_val = 0;
517 	int			count;
518 	int			flag = FALSE;
519 	int			factor = 4;
520 	int			multiplier = 25;
521 	int			number_of_stars = 0;
522 	char		buffer[256];
523 	long double skip = s->skip * s->block_size;
524 
525 	long double tot_bytes = (long double)((i->total_bytes));
526 	tot_bytes -= skip;
527 	if (i->total_bytes > 0)
528 		{
529 		percentDone = (((long double)pos) / ((long double)tot_bytes)) * 100;
530 		if (percentDone != last_val)
531 			flag = TRUE;
532 		last_val = percentDone;
533 		}
534 	else
535 		{
536 		flag = TRUE;
537 		factor = 4;
538 		multiplier = 25;
539 		}
540 
541 	if (flag)
542 		{
543 		number_of_stars = percentDone / factor;
544 
545 		printf("%s: |", s->input_file);
546 		for (count = 0; count < number_of_stars; count++)
547 			{
548 			printf("*");
549 			}
550 
551 		for (count = 0; count < (multiplier - number_of_stars); count++)
552 			{
553 			printf(" ");
554 			}
555 
556 		if (i->total_bytes > 0)
557 			{
558 			printf("|\t %d%% done\n", percentDone);
559 			}
560 		else
561 			{
562 			printf("|\t %s done\n", human_readable(pos, buffer));
563 
564 			}
565 		}
566 
567 	if (percentDone == 100)
568 		{
569 		last_val = 0;
570 		}
571 
572 	return TRUE;
573 }
574