home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
VIRUS
/
STEALTH.ZIP
/
FILECHCK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-10
|
6KB
|
241 lines
/*
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);
}