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

  1. /*
  2. syscheck.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 the computer system for viruses by looking for
  15. inconsistencies in the operating system.  It does so by comparing DOS and BIOS
  16. memory, checking for interrupts set beyond the code space of the program, and
  17. checking interrupts for hijacking code.
  18.  
  19.     This code is public domain.
  20. */
  21.  
  22.  
  23. #if (defined(M_I86SM) || defined(M_I86MM) || defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) && !defined(_MSC_VER) && !defined(_QC)
  24. #define _MSC_VER
  25. #endif
  26.  
  27. #if !defined(__BORLANDC__) && !defined(__TURBOC__) && !defined(_MSC_VER) && !defined(_QC)
  28. #error Unknown compiler.
  29. #endif
  30.  
  31.  
  32. #include <bios.h>
  33. #include <dos.h>
  34. #include <stdlib.h>
  35.  
  36. #include "vircheck.h"
  37. #include "dosmcb.h"
  38.  
  39.  
  40. #if defined(__BORLANDC__) || defined(__TURBOC__)
  41.  
  42. typedef
  43.   void interrupt (*intr_ptr)();
  44.  
  45. #elif defined(_MSC_VER) || defined(_QC)
  46.  
  47. typedef
  48.   void (interrupt far *intr_ptr)();
  49.  
  50. #define getvect  _dos_getvect
  51. #define setvect  _dos_setvect
  52.  
  53. #if !defined(MK_FP)
  54. #define MK_FP(seg, off)  ((void far *)(((unsigned long)(seg) << 16) | (off)))
  55. #endif
  56.  
  57. #define biosmemory  _bios_memsize
  58.  
  59. #endif
  60.  
  61.  
  62. /***/
  63. /* Determine true segment address of pointer and check for wrap around memory. */
  64. unsigned ptrseg(void far * ptr)
  65. {
  66. unsigned pseg;
  67.  
  68. if ((pseg = FP_SEG(ptr) + (FP_OFF(ptr) >> 4)) < FP_SEG(ptr))
  69.   /* Pointer points beyond standard 1M memory. */
  70.   pseg = 0xFFFF;
  71.  
  72. return (pseg);
  73. }
  74.  
  75.  
  76. /***/
  77. /* Validate interrupt; make sure not beyond code space and not hijacked. */
  78. static unsigned validateintr(int intrnum, unsigned memlimit)
  79. {
  80. /* Assume interrupt is valid. */
  81. unsigned result = STEALTH_OK;
  82.  
  83. union
  84.   {
  85.   intr_ptr iptr;                /* Interrupt pointer. */
  86.   const byte far *codeptr;      /* Pointer to interrupt; treat as data. */
  87.   } i;
  88. unsigned iseg;                  /* Adjusted segment of i.iptr. */
  89. intr_ptr target;        /* Target of hijacked interrupt. */
  90.  
  91. /* Get interrupt and adjusted segment. */
  92. i.iptr = getvect(intrnum);
  93. iseg = ptrseg(i.iptr);
  94.  
  95. /* Interrupt pointer invalid if between PSP and memory limit. */
  96. if (iseg >= _psp && iseg < memlimit)
  97.   result |= STEALTH_INTR_ERR;
  98.  
  99. /* Check beginning of interrupt code for suspicious instructions. */
  100. switch (*i.codeptr)
  101.   {
  102.   case 0xEA:    /* JMP FAR <addr>. */
  103.   case 0x9A:    /* CALL FAR <addr>. */
  104.     target = *(intr_ptr far *)(i.codeptr + 1);
  105.     result |= STEALTH_DOS_HIJACKED;
  106.     break;
  107.  
  108.   case 0x2E:    /* CS segment prefix. */
  109.     switch (*(const word far *)(i.codeptr + 1))
  110.       {
  111.       case 0x2EFF:    /* JMP FAR CS:[addr]. */
  112.       case 0x1EFF:    /* CALL FAR CS:[addr]. */
  113.     target = *(intr_ptr far *)MK_FP(FP_SEG(i.codeptr), *(word far *)(i.codeptr + 3));
  114.     result |= STEALTH_DOS_HIJACKED;
  115.     break;
  116.       }
  117.   }
  118.  
  119. if (result & STEALTH_DOS_HIJACKED)
  120.   {
  121.   MCB far *intrmcb;
  122.   MCB far *targetmcb;
  123.  
  124.   /* Determine MCB's that own the interrupt and the target of the redirection. */
  125.   intrmcb = mcb_owner(i.codeptr);
  126.   targetmcb = mcb_owner(target);
  127.  
  128.   /* Redirection is valid if it falls within the same MCB or falls outside memory limit. */
  129.   if (intrmcb == targetmcb || ptrseg(target) >= memlimit)
  130.     result &= ~STEALTH_DOS_HIJACKED;
  131.   }
  132.  
  133. return (result);
  134. }
  135.  
  136.  
  137. /***/
  138. /* Perform anti-virus system check. */
  139. unsigned stealth_sys_check(void)
  140. {
  141. /* Assume system passes all tests. */
  142. unsigned result = STEALTH_OK;
  143.  
  144. MCB far *mcb;        /* Memory control block pointer. */
  145. unsigned biosmem;    /* Memory in paragraphs according to BIOS. */
  146. unsigned dosmem;    /* Memory in paragraphs according to DOS. */
  147. unsigned memlimit;    /* Limit of useable memory. */
  148.  
  149. biosmem = (unsigned)biosmemory() * 64;
  150.  
  151. /* Find last memory control block. */
  152. for (mcb = getmcb(); mcb->id != 0x5A; mcb = nextmcb(mcb));
  153.  
  154. dosmem = FP_SEG(mcb) + mcb->size + 1;
  155.  
  156. /* DOS memory extenders may show more memory than BIOS and some versions of DOS may differ by up to 1k from BIOS memory. */
  157. if (biosmem > dosmem + 64)
  158.   result |= STEALTH_DOS_MEM_ERR;
  159.  
  160. /* Assume BIOS memory goes at least to 640k limit (may have been modified by virus). */
  161. memlimit = max((unsigned)0xA000, biosmem);
  162. memlimit = max(memlimit, dosmem);
  163.  
  164. result |= validateintr(0x21, memlimit);    /* DOS function interrupt. */
  165. result |= validateintr(0x24, memlimit);    /* Critical error interrupt. */
  166. result |= validateintr(0x25, memlimit);    /* Absolute disk read interrupt. */
  167. result |= validateintr(0x26, memlimit);    /* Absolute disk write interrupt. */
  168. result |= validateintr(0x1C, memlimit);    /* User timer interrupt. */
  169. result |= validateintr(0x28, memlimit);    /* DOS OK interrupt. */
  170.  
  171. return (result);
  172. }
  173.