home *** CD-ROM | disk | FTP | other *** search
- /*
- filechck.c
- Stealth Bomber Version 2.2
-
- Kevin Dean
- Fairview Mall P.O. Box 55074
- 1800 Sheppard Avenue East
- Willowdale, Ontario
- CANADA M2J 5B9
- CompuServe ID: 76336,3114
-
- February 10, 1992
-
- This module checks a file for consistency. It checks the file
- date/time stamp, compares the file size from a directory search with the size
- returned by opening the file, and then checks the CRC of the file against the
- CRC passed to it. The code was designed as an anti-virus algorithm.
-
- This code will not detect all viruses that attach themselves to files.
- There are some that are capable of circumventing all these checks. For this
- reason, the stealth_sys_check() function should be called first to check the
- system itself for viruses before calling this function.
-
- This code is public domain.
- */
-
-
- #if (defined(M_I86SM) || defined(M_I86MM) || defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) && !defined(_MSC_VER) && !defined(_QC)
- #define _MSC_VER
- #endif
-
- #if !defined(__BORLANDC__) && !defined(__TURBOC__) && !defined(_MSC_VER) && !defined(_QC)
- #error Unknown compiler.
- #endif
-
- #if defined(__BORLANDC__) || defined(__TURBOC__)
- #include <dir.h>
- #endif
- #include <dos.h>
- #include <io.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "vircheck.h"
-
-
- #if defined(_MSC_VER) || defined(_QC)
-
- extern char **__argv;
- #define _argv __argv
-
- #define MAXPATH 80
- #define MAXDRIVE 3
- #define MAXDIR 66
-
- #define ffblk find_t
-
- #define ff_ftime wr_time
- #define ff_fsize size
-
- struct ftime
- {
- unsigned ft_tsec : 5; /* Two-second interval. */
- unsigned ft_min : 6; /* Minutes */
- unsigned ft_hour : 5; /* Hours */
- unsigned ft_day : 5; /* Days */
- unsigned ft_month : 4; /* Months */
- unsigned ft_year : 7; /* Year */
- };
-
- #define findfirst(path, buffer, attrib) _dos_findfirst(path, attrib, buffer)
- #define findnext _dos_findnext
-
- #define FA_RDONLY _A_RDONLY
- #define FA_HIDDEN _A_HIDDEN
- #define FA_SYSTEM _A_SYSTEM
- #define FA_LABEL _A_VOLID
- #define FA_DIREC _A_SUBDIR
- #define FA_ARCH _A_ARCH
-
- #endif
-
-
- /***/
- /* Check file header consistency and calculate CRC of file. */
- unsigned stealth_file_check(const char *filename, filecrc fcrc)
- {
- /* Assume file passes all tests. */
- unsigned result = STEALTH_OK;
-
- char fn[MAXPATH]; /* Complete file name with path. */
-
- struct ffblk dirinfo; /* File directory information. */
-
- /* If name contains drive or directory, use unmodified, else build full name. */
- if (filename[1] == ':' || strchr(filename, '\\'))
- strcpy(fn, filename);
- else
- {
- /* Assume file not found. */
- fn[0] = 0;
-
- /* DOS versions 3 and above save program name in _argv[0]. */
- if (_osmajor >= 3)
- {
- char *sptr;
-
- strcpy(fn, _argv[0]);
-
- /* Find last subdirectory delimiter. */
- if ((sptr = strrchr(fn, '\\')) != NULL)
- /* Clear file name. */
- *(sptr + 1) = 0;
- /* Check for drive designator. */
- else if (fn[1] == ':')
- /* Clear file name. */
- fn[2] = 0;
- else
- /* _argv[0] is file name only. */
- fn[0] = 0;
-
- /* Merge drive and directory with file name. */
- strcat(fn, filename);
-
- /* Attempt to access file; if failed, pass control onto path search. */
- if (access(fn, 4))
- fn[0] = 0;
- }
-
- if (!fn[0])
- {
- #if defined(__BORLANDC__) || defined(__TURBOC__)
-
- /* Search path for file. */
- const char *fnptr = searchpath(filename);
-
- /* Copy file name if found. */
- if (fnptr)
- strcpy(fn, fnptr);
-
- #elif defined(_MSC_VER) || defined(_QC)
-
- _searchenv((char *)filename, getenv("PATH"), fn);
-
- #endif
- }
- }
-
- if (fn[0] && !findfirst(fn, &dirinfo, FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH))
- {
- struct ftime *timestamp; /* Pointer to timestamp within dirinfo. */
- FILE *f;
- byte *buffer; /* Buffer for program image. */
- size_t bufsize; /* Buffer size. */
-
- /* ftime structure maps over time and date in ffblk structure. */
- timestamp = (struct ftime *)&dirinfo.ff_ftime;
-
- /* Check file time, day, and year. */
- if (timestamp->ft_tsec * 2 > 59 || timestamp->ft_min > 59 || timestamp->ft_hour > 23 ||
- timestamp->ft_day == 0 || timestamp->ft_year >= 100)
- result |= STEALTH_FILE_DATE_ERR;
-
- /* Check month and day based on month. */
- switch (timestamp->ft_month)
- {
- case 4:
- case 6:
- case 9:
- case 11:
- /* Thirty days hath September, April, June, and November. */
- if (timestamp->ft_day > 30)
- result |= STEALTH_FILE_DATE_ERR;
- break;
-
- case 1:
- case 3:
- case 5:
- case 7:
- case 8:
- case 10:
- case 12:
- /* All the rest have thirty-one, excepting February alone. */
- if (timestamp->ft_day > 31)
- result |= STEALTH_FILE_DATE_ERR;
- break;
-
- case 2:
- /* February hath twenty-eight days clear, and twenty-nine in each leap year. */
- if (timestamp->ft_day > (timestamp->ft_year % 4 ? 28 : 29))
- result |= STEALTH_FILE_DATE_ERR;
- break;
-
- default:
- result |= STEALTH_FILE_DATE_ERR;
- break;
- }
-
- f = fopen(fn, "rb");
-
- if (f)
- {
- /* Seek to end of file and compare length to length returned by directory search. */
- fseek(f, 0L, SEEK_END);
- if (ftell(f) != dirinfo.ff_fsize)
- result |= STEALTH_FILE_SIZE_ERR;
-
- /* Rewind file. */
- rewind(f);
-
- /* Make sure that polynomial has its last bit and at least one other set. */
- if (!(fcrc.x.polynomial & 0x00000001) || fcrc.x.polynomial == 0x00000001)
- result |= STEALTH_CRC_BAD_POLY;
-
- /* Allocate 16k buffer if possible, but get at least 512 bytes. */
- bufsize = 16384;
- buffer = bufalloc(&bufsize, 512);
-
- if (buffer)
- {
- /* CRC is valid if calculated CRC matches what is stored in fcrc. */
- if (fcrc.x.crc != calccrc(f, buffer, bufsize, fcrc.x.polynomial))
- result |= STEALTH_CRC_INVALID;
-
- free(buffer);
- }
- else
- result |= STEALTH_NO_MEM;
-
- fclose(f);
- }
- else
- result |= STEALTH_FILE_ERR;
- }
- else
- result |= STEALTH_FILE_ERR;
-
- return (result);
- }
-