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

  1. /*
  2. filechck.c
  3. Stealth Bomber Version 2.2
  4.  
  5. Kevin Dean
  6. Fairview Mall P.O. Box 55074
  7. 1800 Sheppard Avenue East
  8. Willowdale, Ontario
  9. CANADA    M2J 5B9
  10. CompuServe ID: 76336,3114
  11.  
  12. February 10, 1992
  13.  
  14.     This module checks a file for consistency.  It checks the file
  15. date/time stamp, compares the file size from a directory search with the size
  16. returned by opening the file, and then checks the CRC of the file against the
  17. CRC passed to it.  The code was designed as an anti-virus algorithm.
  18.  
  19.     This code will not detect all viruses that attach themselves to files.
  20. There are some that are capable of circumventing all these checks.  For this
  21. reason, the stealth_sys_check() function should be called first to check the
  22. system itself for viruses before calling this function.
  23.  
  24.     This code is public domain.
  25. */
  26.  
  27.  
  28. #if (defined(M_I86SM) || defined(M_I86MM) || defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) && !defined(_MSC_VER) && !defined(_QC)
  29. #define _MSC_VER
  30. #endif
  31.  
  32. #if !defined(__BORLANDC__) && !defined(__TURBOC__) && !defined(_MSC_VER) && !defined(_QC)
  33. #error Unknown compiler.
  34. #endif
  35.  
  36. #if defined(__BORLANDC__) || defined(__TURBOC__)
  37. #include <dir.h>
  38. #endif
  39. #include <dos.h>
  40. #include <io.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44.  
  45. #include "vircheck.h"
  46.  
  47.  
  48. #if defined(_MSC_VER) || defined(_QC)
  49.  
  50. extern char **__argv;
  51. #define _argv  __argv
  52.  
  53. #define MAXPATH   80
  54. #define MAXDRIVE  3
  55. #define MAXDIR    66
  56.  
  57. #define ffblk  find_t
  58.  
  59. #define ff_ftime  wr_time
  60. #define ff_fsize  size
  61.  
  62. struct ftime
  63.   {
  64.   unsigned ft_tsec  : 5;        /* Two-second interval. */
  65.   unsigned ft_min   : 6;        /* Minutes */
  66.   unsigned ft_hour  : 5;        /* Hours */
  67.   unsigned ft_day   : 5;        /* Days */
  68.   unsigned ft_month : 4;        /* Months */
  69.   unsigned ft_year  : 7;        /* Year */
  70.   };
  71.  
  72. #define findfirst(path, buffer, attrib)  _dos_findfirst(path, attrib, buffer)
  73. #define findnext                         _dos_findnext
  74.  
  75. #define FA_RDONLY  _A_RDONLY
  76. #define FA_HIDDEN  _A_HIDDEN
  77. #define FA_SYSTEM  _A_SYSTEM
  78. #define FA_LABEL   _A_VOLID
  79. #define FA_DIREC   _A_SUBDIR
  80. #define FA_ARCH    _A_ARCH
  81.  
  82. #endif
  83.  
  84.  
  85. /***/
  86. /* Check file header consistency and calculate CRC of file. */
  87. unsigned stealth_file_check(const char *filename, filecrc fcrc)
  88. {
  89. /* Assume file passes all tests. */
  90. unsigned result = STEALTH_OK;
  91.  
  92. char fn[MAXPATH];    /* Complete file name with path. */
  93.  
  94. struct ffblk dirinfo;    /* File directory information. */
  95.  
  96. /* If name contains drive or directory, use unmodified, else build full name. */
  97. if (filename[1] == ':' || strchr(filename, '\\'))
  98.   strcpy(fn, filename);
  99. else
  100.   {
  101.   /* Assume file not found. */
  102.   fn[0] = 0;
  103.  
  104.   /* DOS versions 3 and above save program name in _argv[0]. */
  105.   if (_osmajor >= 3)
  106.     {
  107.     char *sptr;
  108.  
  109.     strcpy(fn, _argv[0]);
  110.  
  111.     /* Find last subdirectory delimiter. */
  112.     if ((sptr = strrchr(fn, '\\')) != NULL)
  113.       /* Clear file name. */
  114.       *(sptr + 1) = 0;
  115.     /* Check for drive designator. */
  116.     else if (fn[1] == ':')
  117.       /* Clear file name. */
  118.       fn[2] = 0;
  119.     else
  120.       /* _argv[0] is file name only. */
  121.       fn[0] = 0;
  122.  
  123.     /* Merge drive and directory with file name. */
  124.     strcat(fn, filename);
  125.  
  126.     /* Attempt to access file; if failed, pass control onto path search. */
  127.     if (access(fn, 4))
  128.       fn[0] = 0;
  129.     }
  130.  
  131.   if (!fn[0])
  132.     {
  133.     #if defined(__BORLANDC__) || defined(__TURBOC__)
  134.  
  135.     /* Search path for file. */
  136.     const char *fnptr = searchpath(filename);
  137.  
  138.     /* Copy file name if found. */
  139.     if (fnptr)
  140.       strcpy(fn, fnptr);
  141.  
  142.     #elif defined(_MSC_VER) || defined(_QC)
  143.  
  144.     _searchenv((char *)filename, getenv("PATH"), fn);
  145.  
  146.     #endif
  147.     }
  148.   }
  149.  
  150. if (fn[0] && !findfirst(fn, &dirinfo, FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH))
  151.   {
  152.   struct ftime *timestamp;    /* Pointer to timestamp within dirinfo. */
  153.   FILE *f;
  154.   byte *buffer;            /* Buffer for program image. */
  155.   size_t bufsize;        /* Buffer size. */
  156.  
  157.   /* ftime structure maps over time and date in ffblk structure. */
  158.   timestamp = (struct ftime *)&dirinfo.ff_ftime;
  159.  
  160.   /* Check file time, day, and year. */
  161.   if (timestamp->ft_tsec * 2 > 59 || timestamp->ft_min > 59 || timestamp->ft_hour > 23 ||
  162.       timestamp->ft_day == 0 || timestamp->ft_year >= 100)
  163.     result |= STEALTH_FILE_DATE_ERR;
  164.  
  165.   /* Check month and day based on month. */
  166.   switch (timestamp->ft_month)
  167.     {
  168.     case 4:
  169.     case 6:
  170.     case 9:
  171.     case 11:
  172.       /* Thirty days hath September, April, June, and November. */
  173.       if (timestamp->ft_day > 30)
  174.     result |= STEALTH_FILE_DATE_ERR;
  175.       break;
  176.  
  177.     case 1:
  178.     case 3:
  179.     case 5:
  180.     case 7:
  181.     case 8:
  182.     case 10:
  183.     case 12:
  184.       /* All the rest have thirty-one, excepting February alone. */
  185.       if (timestamp->ft_day > 31)
  186.     result |= STEALTH_FILE_DATE_ERR;
  187.       break;
  188.  
  189.     case 2:
  190.       /* February hath twenty-eight days clear, and twenty-nine in each leap year. */
  191.       if (timestamp->ft_day > (timestamp->ft_year % 4 ? 28 : 29))
  192.     result |= STEALTH_FILE_DATE_ERR;
  193.       break;
  194.  
  195.     default:
  196.       result |= STEALTH_FILE_DATE_ERR;
  197.       break;
  198.     }
  199.  
  200.   f = fopen(fn, "rb");
  201.  
  202.   if (f)
  203.     {
  204.     /* Seek to end of file and compare length to length returned by directory search. */
  205.     fseek(f, 0L, SEEK_END);
  206.     if (ftell(f) != dirinfo.ff_fsize)
  207.       result |= STEALTH_FILE_SIZE_ERR;
  208.  
  209.     /* Rewind file. */
  210.     rewind(f);
  211.  
  212.     /* Make sure that polynomial has its last bit and at least one other set. */
  213.     if (!(fcrc.x.polynomial & 0x00000001) || fcrc.x.polynomial == 0x00000001)
  214.       result |= STEALTH_CRC_BAD_POLY;
  215.  
  216.     /* Allocate 16k buffer if possible, but get at least 512 bytes. */
  217.     bufsize = 16384;
  218.     buffer = bufalloc(&bufsize, 512);
  219.  
  220.     if (buffer)
  221.       {
  222.       /* CRC is valid if calculated CRC matches what is stored in fcrc. */
  223.       if (fcrc.x.crc != calccrc(f, buffer, bufsize, fcrc.x.polynomial))
  224.     result |= STEALTH_CRC_INVALID;
  225.  
  226.       free(buffer);
  227.       }
  228.     else
  229.       result |= STEALTH_NO_MEM;
  230.  
  231.     fclose(f);
  232.     }
  233.   else
  234.     result |= STEALTH_FILE_ERR;
  235.   }
  236. else
  237.   result |= STEALTH_FILE_ERR;
  238.  
  239. return (result);
  240. }
  241.