home *** CD-ROM | disk | FTP | other *** search
- /*
- syscheck.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 the computer system for viruses by looking for
- inconsistencies in the operating system. It does so by comparing DOS and BIOS
- memory, checking for interrupts set beyond the code space of the program, and
- checking interrupts for hijacking code.
-
- 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
-
-
- #include <bios.h>
- #include <dos.h>
- #include <stdlib.h>
-
- #include "vircheck.h"
- #include "dosmcb.h"
-
-
- #if defined(__BORLANDC__) || defined(__TURBOC__)
-
- typedef
- void interrupt (*intr_ptr)();
-
- #elif defined(_MSC_VER) || defined(_QC)
-
- typedef
- void (interrupt far *intr_ptr)();
-
- #define getvect _dos_getvect
- #define setvect _dos_setvect
-
- #if !defined(MK_FP)
- #define MK_FP(seg, off) ((void far *)(((unsigned long)(seg) << 16) | (off)))
- #endif
-
- #define biosmemory _bios_memsize
-
- #endif
-
-
- /***/
- /* Determine true segment address of pointer and check for wrap around memory. */
- unsigned ptrseg(void far * ptr)
- {
- unsigned pseg;
-
- if ((pseg = FP_SEG(ptr) + (FP_OFF(ptr) >> 4)) < FP_SEG(ptr))
- /* Pointer points beyond standard 1M memory. */
- pseg = 0xFFFF;
-
- return (pseg);
- }
-
-
- /***/
- /* Validate interrupt; make sure not beyond code space and not hijacked. */
- static unsigned validateintr(int intrnum, unsigned memlimit)
- {
- /* Assume interrupt is valid. */
- unsigned result = STEALTH_OK;
-
- union
- {
- intr_ptr iptr; /* Interrupt pointer. */
- const byte far *codeptr; /* Pointer to interrupt; treat as data. */
- } i;
- unsigned iseg; /* Adjusted segment of i.iptr. */
- intr_ptr target; /* Target of hijacked interrupt. */
-
- /* Get interrupt and adjusted segment. */
- i.iptr = getvect(intrnum);
- iseg = ptrseg(i.iptr);
-
- /* Interrupt pointer invalid if between PSP and memory limit. */
- if (iseg >= _psp && iseg < memlimit)
- result |= STEALTH_INTR_ERR;
-
- /* Check beginning of interrupt code for suspicious instructions. */
- switch (*i.codeptr)
- {
- case 0xEA: /* JMP FAR <addr>. */
- case 0x9A: /* CALL FAR <addr>. */
- target = *(intr_ptr far *)(i.codeptr + 1);
- result |= STEALTH_DOS_HIJACKED;
- break;
-
- case 0x2E: /* CS segment prefix. */
- switch (*(const word far *)(i.codeptr + 1))
- {
- case 0x2EFF: /* JMP FAR CS:[addr]. */
- case 0x1EFF: /* CALL FAR CS:[addr]. */
- target = *(intr_ptr far *)MK_FP(FP_SEG(i.codeptr), *(word far *)(i.codeptr + 3));
- result |= STEALTH_DOS_HIJACKED;
- break;
- }
- }
-
- if (result & STEALTH_DOS_HIJACKED)
- {
- MCB far *intrmcb;
- MCB far *targetmcb;
-
- /* Determine MCB's that own the interrupt and the target of the redirection. */
- intrmcb = mcb_owner(i.codeptr);
- targetmcb = mcb_owner(target);
-
- /* Redirection is valid if it falls within the same MCB or falls outside memory limit. */
- if (intrmcb == targetmcb || ptrseg(target) >= memlimit)
- result &= ~STEALTH_DOS_HIJACKED;
- }
-
- return (result);
- }
-
-
- /***/
- /* Perform anti-virus system check. */
- unsigned stealth_sys_check(void)
- {
- /* Assume system passes all tests. */
- unsigned result = STEALTH_OK;
-
- MCB far *mcb; /* Memory control block pointer. */
- unsigned biosmem; /* Memory in paragraphs according to BIOS. */
- unsigned dosmem; /* Memory in paragraphs according to DOS. */
- unsigned memlimit; /* Limit of useable memory. */
-
- biosmem = (unsigned)biosmemory() * 64;
-
- /* Find last memory control block. */
- for (mcb = getmcb(); mcb->id != 0x5A; mcb = nextmcb(mcb));
-
- dosmem = FP_SEG(mcb) + mcb->size + 1;
-
- /* DOS memory extenders may show more memory than BIOS and some versions of DOS may differ by up to 1k from BIOS memory. */
- if (biosmem > dosmem + 64)
- result |= STEALTH_DOS_MEM_ERR;
-
- /* Assume BIOS memory goes at least to 640k limit (may have been modified by virus). */
- memlimit = max((unsigned)0xA000, biosmem);
- memlimit = max(memlimit, dosmem);
-
- result |= validateintr(0x21, memlimit); /* DOS function interrupt. */
- result |= validateintr(0x24, memlimit); /* Critical error interrupt. */
- result |= validateintr(0x25, memlimit); /* Absolute disk read interrupt. */
- result |= validateintr(0x26, memlimit); /* Absolute disk write interrupt. */
- result |= validateintr(0x1C, memlimit); /* User timer interrupt. */
- result |= validateintr(0x28, memlimit); /* DOS OK interrupt. */
-
- return (result);
- }
-