home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TROJAN_P / VKILL13.ZIP / VKILL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-21  |  8.5 KB  |  323 lines

  1.  /*
  2.   * file vkill.c
  3.   *
  4.   * Author: Antonio Julio Raposo (ajr@cybill.inesc.pt - LISBOA - PORTUGAL)
  5.   * (Please do not remove my name from this file)
  6.   * This is version 1.3, public domain software, meaning
  7.   * no copyright and *** NO RESPONSABILITY ***
  8.   *
  9.   * usage:
  10.   *  1) compile with Borland's TURBOC 2.0 or equivalent (COMPACT model)
  11.   *  2) run with a command like 'VKILL C:' to clean drive C
  12.   *  3) if it stops accessing the disk and seems stuck, just reset the
  13.   *     computer and start over again (this probably will only hapen if you
  14.   *     compile a small model or if there are thousands of virus around)
  15.   *
  16.   *  4) I hope you start checking the software you copy, starting a year ago!
  17.   */
  18. #ifndef __COMPACT__
  19. #  error "must compile with compact model (near functions and far data)"
  20. #endif
  21.  
  22.  /*
  23.   * Changes from Vkill 1.2:
  24.   *   - modified the display of files being checked
  25.   *   - now allows the search of only one file or directory
  26.   *   - added search only mode, without touching the files
  27.   * Changes from Vkill 1.1 (beta test version):
  28.   *   - fixed some minor bugs in the protection scheme
  29.   *   - added a line showing the name of the file being scanned
  30.   * Changes from Vkill 1.0:
  31.   *   - fixed bug that prevented .EXE files wich had changed in size from
  32.   *    beeing cleaned (may happen if you append something to the end of
  33.   *    the file.) now the excess length also gets thrown away.
  34.   *   - added a feature wich protects the files from beeing infected.
  35.   *   - scans also .BIN and .OVL files as .EXE overlays.
  36.   */
  37.  
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <dir.h>
  41. #include <io.h>
  42. #include <dos.h>
  43. #include <alloc.h>
  44. #include <ctype.h>
  45. #include <fcntl.h>
  46.  
  47. #define _COM 5
  48. #define _EXE 6
  49. #define chmod(s,m) _chmod (s, 1, m)
  50.  
  51. char *pcat (char *, char *);
  52. char *signature =
  53.   "8ED0BC000750B8C50050CBFC062E8C0631002E8C0639002E8C063D002E8C0641008CC0";
  54. char *buffer;
  55.  
  56. struct {
  57.   int dirs, total, com, exe, prot;
  58. } statistics;
  59. int prot = 0, clean = 1;
  60.  
  61. main (int argc, char *argv[])
  62. {
  63.   char *root, *s, *t, i;
  64.  
  65.   printf ("\n\n VKILL 1.3  -  October 1990\n\n");
  66.   printf ("Author: Antonio Julio Raposo. LISBOA - PORTUGAL\n");
  67.   printf ("e-mail: ajr@cybill.inesc.pt\n\n");
  68.   printf ("Mission:\t*** Seek and Terminate. ***\n");
  69.   printf ("Target: \t*** Jerusalem-B virus. ***\n");
  70.   printf ("\tWARNING! The virus damages some files beyond recovery.\n\n");
  71.  
  72.   for (s = signature, t = signature ; *s ; s += 2, t++)
  73.     *t = (*s > '9' ? *s - 'A' + 10 : *s - '0') * 16 +
  74.      (s[1] > '9' ? s[1] - 'A' + 10 : s[1] - '0');
  75.   *t = '\0';
  76.   if ((buffer = farmalloc (0x10000L)) == NULL)
  77.     {
  78.       fprintf (stderr, "not enough memory to run!\n");
  79.       exit (2);
  80.     }
  81.   /* get arguments from command line */
  82.   if (argc < 2)
  83.     usage (*argv);
  84.   for (i = 1 ; i < argc ; i++)
  85.     if (*argv[i] == '/' || *argv[i] == '-')
  86.       for (t = argv[i] + 1 ; *t ; t++)
  87.     switch (*t)
  88.       {
  89.         case 'p': prot = 1; break;
  90.         case 'u': prot = -1; break;
  91.         case 'n': clean = 0; break;
  92.         default: fprintf (stderr, "unknown option /%c. ignored.\n", *t);
  93.       }
  94.     else if (argv[i][1] == ':' && argv[i][2] == '\0')
  95.       {
  96.     root = malloc (4);
  97.     sprintf (root, "%c:\\", toupper (*argv[i]));
  98.     printf ("reading all files\n\n");
  99.     if (readdir (root))
  100.       {
  101.         fprintf (stderr, "couldn't find any files?!\n\nABORTED\n");
  102.       }
  103.     free (root);
  104.       }
  105.     else
  106.       {
  107.     struct ffblk ff;
  108.  
  109.     if (readdir (argv[i]) && !findfirst (argv[i], &ff, 0x37) &&
  110.         !access (argv[i], 0))
  111.       {
  112.         readfile (argv[i], &ff);
  113.         printf ("\n");
  114.       }
  115.       }
  116.  
  117.   printf ("\t\t\t\n\n%d directories searched\n", statistics.dirs);
  118.   printf ("%d files examined\n", statistics.total);
  119.   printf ("%d virus found in com files\n", statistics.com);
  120.   printf ("%d virus found in exe files\n", statistics.exe);
  121.   if (prot < 0)
  122.     printf ("%d protections removed\n", statistics.prot);
  123.   else if (prot > 0)
  124.     printf ("%d files protected\n", statistics.prot);
  125.   printf ("\n\nMission Completed\n\n\n");
  126. }
  127.  
  128. int usage (char *name)
  129. {
  130.   fprintf (stderr, "usage:\t%s [/pun] <drive letter>:[filename]\n", name);
  131.   fprintf (stderr, "\t/p to protect files\n");
  132.   fprintf (stderr, "\t/u to unprotect files\n");
  133.   fprintf (stderr, "\t/n search without cleaning\n");
  134.   exit (1);
  135. }
  136.  
  137. int readdir (char *s)
  138. {
  139.   struct ffblk ff;
  140.   char *all, *file;
  141.  
  142.   all = pcat (s, "*.*");
  143.   if (findfirst (all, &ff, 0x37))
  144.     {
  145.       free (all);
  146.       return -1;
  147.     }
  148.   printf ("searching files in %s\n", s);
  149.   /* first pass: plain files */
  150.   do
  151.     if (!(ff.ff_attrib & FA_DIREC))
  152.       {
  153.     file = pcat (s, ff.ff_name);
  154.     readfile (file, &ff);
  155.     free (file);
  156.       }
  157.   while (!findnext (&ff));
  158.   /* second pass: subdirectories */
  159.   findfirst (all, &ff, 0x37);
  160.   do
  161.     if ((ff.ff_attrib & FA_DIREC) && *ff.ff_name != '.')
  162.       {
  163.     file = pcat (s, ff.ff_name);
  164.     readdir (file);
  165.     free (file);
  166.       }
  167.   while (!findnext (&ff));
  168.   free (all);
  169.   statistics.dirs++;
  170.   return 0;
  171. }
  172.  
  173. readfile (char *s, struct ffblk *ff)
  174. {
  175.   int fd, ftype, virus;
  176.   char *ext;
  177.   long offset;
  178.  
  179.   ext = strchr (ff->ff_name, '.') + 1;
  180.   if (!strcmp (ext, "COM"))
  181.     ftype = _COM;
  182.   else if (!strcmp (ext, "EXE") || !strcmp (ext, "BIN") ||
  183.        !strcmp (ext, "OVL") || !strcmp (ext, "OVG") ||
  184.        !strcmp (ext, "OV1") || !strcmp (ext, "OV2") ||
  185.        !strcmp (ext, "OVR"))
  186.     ftype = _EXE;
  187.   else
  188.     return;
  189.   printf ("%-20s\r", ff->ff_name);
  190.   virus = 1;
  191.   do
  192.     {
  193.       fd = open (s, O_RDONLY | O_BINARY);
  194.       lseek (fd, 0L, SEEK_SET);
  195.       if (ftype == _EXE)
  196.     {
  197.       unsigned *up;
  198.       read (fd, buffer, 0x710);
  199.       up = (unsigned *) buffer;
  200.       offset = -0xC5L + 0x10L * (up[4] + up[11]) + up[10];
  201.       lseek (fd, offset, SEEK_SET);
  202.     }
  203.       read (fd, buffer, 0x710);
  204.       close (fd);
  205.       if (!strcmp (buffer + 0xBA, signature))
  206.     if (ftype == _EXE)
  207.       cleanEXE (s, ff, offset);
  208.     else
  209.       cleanCOM (s, ff);
  210.       else
  211.     virus = 0;
  212.       if (virus)
  213.     printf ("virus found in file %s. %s\007\n",
  214.         s, clean ? "" : "(not cleaned)\007");
  215.     }
  216.   while (virus && clean); /* file my be infected with more than one copy */
  217.   if (prot)
  218.     protect (s, ff);
  219.   statistics.total++;
  220. }
  221.  
  222. cleanCOM (char *s, struct ffblk *ff)
  223. {
  224.   int fd;
  225.   struct ftime ft;
  226.  
  227.   statistics.com ++;
  228.   if (!clean)
  229.     return;
  230.   chmod (s, 0);
  231.   fd = open (s, O_RDWR | O_BINARY);
  232.   getftime (fd, &ft);
  233.   lseek (fd, 0L, SEEK_SET);
  234.   read (fd, buffer, ff->ff_fsize);
  235.   lseek (fd, 0L, SEEK_SET);
  236.   write (fd, buffer + 0x710, ff->ff_fsize - 0x710);
  237.   chsize (fd, ff->ff_fsize - 0x710L);
  238.   ff->ff_fsize -= 0x710L;
  239.   setftime (fd, &ft);
  240.   close (fd);
  241.   chmod (s, ff->ff_attrib);
  242. }
  243.  
  244. cleanEXE (char *s, struct ffblk *ff, long offset)
  245. {
  246.   int fd;
  247.   struct ftime ft;
  248.   unsigned istack_hi, istack_lo, entry_hi, entry_lo, pages, byteslp;
  249.  
  250.   statistics.exe ++;
  251.   if (!clean)
  252.     return;
  253.   chmod (s, 0);
  254.   fd = open (s, O_RDWR | O_BINARY);
  255.   getftime (fd, &ft);
  256.   istack_hi = *(unsigned *) (buffer + 0x45);
  257.   istack_lo = *(unsigned *) (buffer + 0x43);
  258.   entry_hi = *(unsigned *) (buffer + 0x47);
  259.   entry_lo = *(unsigned *) (buffer + 0x49);
  260.   byteslp = (unsigned) (offset % 0x200L);
  261.   pages = (unsigned) (offset / 0x200L);
  262.   if (byteslp != 0)
  263.     pages++;
  264.   chsize (fd, ff->ff_fsize = offset);
  265.   lseek (fd, 0L, SEEK_SET);
  266.   read (fd, buffer, 0x1C);
  267.   lseek (fd, 0L, SEEK_SET);
  268.   *(unsigned *) (buffer + 0x0E) = istack_hi;
  269.   *(unsigned *) (buffer + 0x10) = istack_lo;
  270.   *(unsigned *) (buffer + 0x14) = entry_hi;
  271.   *(unsigned *) (buffer + 0x16) = entry_lo;
  272.   *(unsigned *) (buffer + 0x04) = pages;
  273.   *(unsigned *) (buffer + 0x02) = byteslp;
  274.   *(unsigned *) (buffer + 0x12) = 0;
  275.   write (fd, buffer, 0x1C);
  276.   setftime (fd, &ft);
  277.   close (fd);
  278.   chmod (s, ff->ff_attrib);
  279. }
  280.  
  281. protect (char *s, struct ffblk *ff)
  282. {
  283.   int fd;
  284.   struct ftime ft;
  285.  
  286.   if (!clean) return;
  287.   chmod (s, 0);
  288.   fd = open (s, O_RDWR | O_BINARY);
  289.   getftime (fd, &ft);
  290.   lseek (fd, -5L, SEEK_END);
  291.   read (fd, buffer, 5);
  292.   if (strncmp (buffer, "MsDos", 5))
  293.     {
  294.       if (prot > 0)
  295.     {
  296.       lseek (fd, 0L, SEEK_END);
  297.       write (fd, "MsDos", 5);
  298.       statistics.prot++;
  299.     }
  300.     }
  301.   else
  302.     if (prot < 0)
  303.       {
  304.     chsize (fd, ff->ff_fsize -= 5L);
  305.     statistics.prot++;
  306.       }
  307.   setftime (fd, &ft);
  308.   close (fd);
  309.   chmod (s, ff->ff_attrib);
  310. }
  311.  
  312. char *pcat (char *path, char *name)
  313. {
  314.   register char *aux;
  315.   register int plen = strlen (path);
  316.   aux = malloc (plen + strlen (name) + 2);
  317.   strcpy (aux, path);
  318.   if (*aux != '\0' && aux[plen - 1] != '\\')
  319.     strcat (aux, "\\");
  320.   strcat (aux, name);
  321.   return aux;
  322. }
  323.