home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1993 May
/
SIMTEL_0593.ISO
/
msdos
/
virus
/
nobrain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-09
|
19KB
|
594 lines
/****************************************************************
Program: NOBRAIN
Author: Carl Fussell
Santa Clara Univ
CARL@SCU.BITNET
Date: April 1988
Descript: Program "cures" diskettes infected with the "Brain" virus.
Only works for DSDD diskettes (though could be easily
modified). But that is all Brain appears to infect at this
point.
Language: Computer Innovations CI86 C Language
Operation: Run it by typing: x> NOBRAIN DRV: [0/1]
where DRV: is the drive containing the "infected" diskette.
The option 0 or 1 is for verbose mode where it dumps contents
of infected sectors, steps being performed, etc. to display.
If specified and non-zero, verbose occurs.
The program first checks to see if the machine itself is
infected. If so, you are asked if you want the machine
"cleansed". If yes, it is and the program proceeds. If no,
the program aborts. You cannot leave the machine infected
but proceed with curing the diskettes.
The program will abort at any time it thinks it has found an
inconsistancy, ie. some portion that does NOT appear to be
infected. The diskette must be "fully infected" before cure will
take place. If it thinks the diskette IS fully infected, then
just before the cure is effected, a confirmation will be asked for.
You can leave the diskette infected if desired.
DISCLAIMER:
I claim no responsibility whatsoever for any havoc, damage,
data loss, or anything else that results from the running of
this program. You use it AT YOUR OWN RISK!! I wrote it to
solve a problem at our site but make absolutely no guarantee
(implied or otherwise) as to its operation. Neither does
Santa Clara University in any way endorse or support the
use of this program nor does it assume any responsibility
for any consequences resulting from the running of this
program.
****************************************************************/
#include <stdio.h>
/* Error Message Definitions */
#define noarg 1
#define invadr 2
#define nofixd 3
/* Misc Definitions */
#define byte unsigned char
#define word unsigned int
/* Global Definitions */
struct regval { unsigned ax,bx,cx,dx,si,di,ds,es; };
struct segval { unsigned scs,sss,sds,ses; } segs;
struct {
byte junk1[3];
char sysid[8];
word sectsize;
byte clustsize;
word resvsects;
byte FATcopies;
word rootdirentries;
word totalsects;
byte idbyte;
word FATsects;
word trksects;
word heads;
word resvspecial;
byte remainder[4*512-30]; } bootinfo;
struct direntry {
char fname[8];
char ext[3];
byte attrib;
byte resvd[10];
word xtime;
word xdate;
word startFAT;
long fsize; };
struct regval rreg,sreg;
struct direntry directory[1024];
int drv;
unsigned char FAT[10*512]; /* allow for 10 sectors though only 4 */
/* are needed for D-9 diskettes */
/* Function Definitions */
int copyvec();
int checkvec();
word gettime();
word getdate();
int findlabel();
int changelabel();
int getFATentry();
int setFATentry();
int dlstoclus();
int infected();
int errorout();
int diskerror();
int diskread();
int bdiskread();
int diskwrite();
int bdiskwrite();
int displayraw();
int homecursor();
int clearscreen();
/************************************************************/
/* Main Program Starts Here */
/************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
int idbyte,sect,i,nsects,done=0,dirsize,dirstart,pc_infected;
unsigned int *p,bogus_clus,f1,f2,f3;
char drvlet, ans[20];
unsigned char bufr[1024],bootrec[512],orig_bootrec[512],virus[6*512];
int bogus_trk,bogus_sect,bogus_side,bogus_dls,bogus_label,dispflag;
if (argc<2) {
printf(" This program is used to eradicate the Brain virus.\n");
printf(" Usage: NOBRAIN drive:\n\n");
printf(" Where drive is the disk drive containing the
infected diskette.\n\n");
printf(" Warning: Probably should use this on a healthy diskette.
It may\n");
printf(" well corrupt the good diskette!\n\n");
exit();
} else {
drvlet = *argv[1];
drv = toupper(drvlet) - 'A' + 1; /* A=1, B=2 */
if (drv<1 || drv>2) {
printf(" Error: Only drive A: or B: may be specified!\n");
exit();
}
dispflag = (argc>2);
}
clearscreen();
if (pc_infected=checkvec(0x13)) {
printf("\nWARNING! This machine has itself been infected and thus\n");
printf(" so has the \"cure\" diskette in all likelihood.\n");
printf(" You can proceed but will probably need to
inoculate\n");
printf(" the \"cure\" diskette too.\7\n");
printf("\n VACCINATE machine itself (Y/N) ?");
scanf("%s",ans);
if (toupper(ans[0])=='Y') {
printf("\n Inoculating the PC...\n");
copyvec(0x6D,0x13);
} else {
printf("\n Cannot \"cure\" diskettes on an infected machine...");
printf("\n Aborting cure....\n");
exit();
} /* else */
} /* if */
printf("\n\nAttempting cure on Drive %c:.... :-)\n",'A'+drv-1);
/* Get boot record */
if (dispflag) printf("\nGetting Boot Record...\n");
diskread(drv,0,1,bootrec) ;
if (dispflag) displayraw(bootrec,1);
if (!infected(bootrec,0x30,"\(c\) 1986 Brain")) {
printf("\nBoot Record Check:\n");
printf("\n This does not appear to be a \"Brain\" infected
diskette.\n");
printf("\n Aborting cure...\n");
exit();
}
/* extra confirmation on signature */
p = &bootrec[4];
if (*p != 0x1234) {
printf("\nBoot Record Signature Check:\n");
printf("\n This does not appear to be a \"Brain\" infected
diskette.\n");
printf("\n Aborting cure...\n");
exit();
}
bogus_side = bootrec[6];
bogus_sect = bootrec[7];
bogus_trk = bootrec[8];
bogus_dls = bogus_trk*9*2 + bogus_side*9 + bogus_sect;
/* Get virus sectors */
if (dispflag) printf("\nGetting virus records...\n");
diskread(drv,bogus_dls,5,virus);
if (!infected(virus,342,"\(c\) 1986 Brain")) {
printf("\nVirus Check:\n");
printf("\n This does not appear to be a \"Brain\" infected
diskette.\n");
printf("\n Aborting cure...\n");
exit();
}
if (dispflag) displayraw(virus,5);
/* Get original Boot record */
if (dispflag) printf("\nGetting original boot record...\n");
diskread(drv,bogus_dls-1,1,orig_bootrec) ;
if (!infected(orig_bootrec,3,"IBM ")) {
printf("\n This appears to be a partially infected \"Brain\" diskette
but\n");
printf(" without a \"healthy\" saved boot record was not found.\n");
printf("\n Aborting cure...\n");
exit();
}
if (dispflag) displayraw(orig_bootrec,1);
/* Get FAT table read in */
if (dispflag) printf("\nGetting FAT table...\n");
diskread(drv,1,4,FAT);
bogus_clus = dlstoclus(bogus_dls);
f1 = getFATentry(bogus_clus);
f2 = getFATentry(bogus_clus+1);
f3 = getFATentry(bogus_clus+2);
if (dispflag) {
printf(" Bogus DLS = %d (%XH)\n",bogus_dls,bogus_dls);
printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
bogus_clus,bogus_clus,f1,f1);
printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
bogus_clus+1,bogus_clus+1,f2,f2);
printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
bogus_clus+2,bogus_clus+2,f3,f3);
}
if (f1!=0xFF7 || f2!=0xFF7 || f3!=0xFF7) {
printf("\n This appears to be a partially infected \"Brain\" diskette
but\n");
printf(" FAT virus clusters were not all marked as bad.\n");
printf("\n Aborting cure...\n");
exit();
}
/* Get directory table */
if (dispflag) printf("\nGetting directory entry...\n");
dirstart = 1 + 4; /* boot sector + FAT size */
dirsize = 7; /* D-9 diskettes have 7 sectors of dir entries */
diskread(drv,dirstart,dirsize,directory);
if (!(bogus_label=findlabel())) {
printf("\n The Virus label was not found on this diskette!\n");
}
/* Repair everything */
printf("\nThis appears to be an infected diskette. \n\n");
printf(" VACCINATE it (Y/N) ?");
scanf("%s",ans);
if (toupper(ans[0])=='Y') {
printf("\n Inoculating the Drive...\n");
setFATentry(bogus_clus,0); /* Update FAT */
setFATentry(bogus_clus+1,0);
setFATentry(bogus_clus+2,0);
changelabel(bogus_label);
diskwrite(drv,0,1,orig_bootrec); /* Replace boot rec */
diskwrite(drv,dirstart,dirsize,directory); /* Write updated direct */
diskwrite(drv,1,4,FAT); /* Write updated FAT */
} else {
printf("\nOK... Aborting!");
exit();
}
printf("\n\n Your diskette should now be \"cured\"!\7\n\n");
if (pc_infected) {
printf("\nREMEMBER! This PC was infected. Be sure to inoculate\n");
printf(" the vaccine diskette in case it was infected!\n");
}
} /* main */
/********************************************************/
int checkvec(vec)
int vec;
{
unsigned int vec_ip,vec_cs,orgvec_ip,orgvec_cs,highmem;
int bad, mem;
bad = 0; /* assume "good" to start */
vec_ip = peek(4*vec,0); /* check if disk vector was altered */
vec_cs = peek(4*vec+2,0);
if (vec_cs < 0xA000) {
highmem=peek(0x413,0); /* check max mem to allow for "funny", */
/* legitimate disk drivers */
for (mem=64,bad=0; mem<=640; mem+=64) {
if (highmem==(mem-7)) {
bad=1; /* if max mem value off by 7K => bad */
break;
} /* if */
} /* for */
} /* if */
return(bad);
} /* checkvec */
/********************************************************/
int copyvec(src,dst)
int src;
int dst;
{
word vec_ip,vec_cs,highmem;
vec_ip = peek(4*src,0); /* get original vector */
vec_cs = peek(4*src+2,0);
pokew(4*dst,0,vec_ip);
pokew(4*dst+2,0,vec_cs);
highmem=peek(0x413,0); /* adjust max mem limit while at it */
highmem += 7; /* get back 7K virus hid in */
pokew(0x413,0,highmem);
return;
} /* copyvec */
/********************************************************/
int changelabel(entry)
int entry;
{
int i;
char *newlabel="Brain Dead ",*p;
for (i=0,p=newlabel; i<11; i++)
directory[entry].fname[i] = *(p+i);
directory[entry].attrib = 8;
for (i=0; i<10; i++) directory[entry].resvd[i] = 0;
directory[entry].xdate = getdate();
directory[entry].xtime = gettime();
directory[entry].startFAT = 0;
directory[entry].fsize = 0L;
} /* deletelabel */
/********************************************************/
int findlabel()
{
int i;
for (i=0; i<112; i++) { /* max 112 entries in D-9 disk */
if (!directory[i].fname[0]) break;
if ( (directory[i].attrib & 0x08) &&
(infected(directory[i].fname,0," (c) Brain ")) ) {
if (!i) { /* label should not be able to be 1st */
printf("\nThis should not occur! Label First! Abort!\n");
exit();
}
return(i);
} /* if */
} /* for */
return(0);
} /* findlabel */
/********************************************************/
word gettime()
{
word time;
sreg.ax = 0x2C00;
sysint21(&sreg,&rreg);
time = ( ((rreg.cx>>8)<<11) | ((rreg.cx&0xFF)<<5) | (rreg.dx>>9) );
/* printf("\nch=%d cl=%d dh=%d time=%x\n",
rreg.cx>>8 , rreg.cx&0xFF, rreg.dx>>8 , time); */
return(time);
} /* gettime */
/********************************************************/
word getdate()
{
word idate;
sreg.ax = 0x2A00;
sysint21(&sreg,&rreg);
idate = ( ((rreg.cx-1980)<<9) | ((rreg.dx>>8)<<5) | (rreg.dx&0xFF) );
/* printf("\ncx = %d dx= %x dh= %d dl= %d date= %x \n",
rreg.cx, rreg.dx, (rreg.dx>>8), (rreg.dx&0xFF), idate); */
return(idate);
} /* getdate */
/********************************************************/
int infected(tgt,pos,src)
char *tgt;
int pos;
char *src;
{
char *p,*q;
int mismatch,len;
len = strlen(src);
for (mismatch=0,p=tgt+pos,q=src; p<tgt+pos+len && !mismatch; p++,q++)
mismatch = (*p != *q);
return(!mismatch);
} /* infected */
/********************************************************/
int dlstoclus(dls)
int dls;
{
return(dls/2-4);
} /* dlstoclus */
/********************************************************/
int getFATentry(clus)
int clus;
{
int index,entry;
unsigned int *p;
index = clus*3/2;
p = &FAT[index];
entry = (clus%2)? *p >> 4 : *p & 0xFFF;
return(entry);
} /* getFATentry */
/********************************************************/
int setFATentry(clus,val)
int clus;
unsigned int val;
{
int index,entry; /* On a D-9 diskette, FAT is 4 sectors */
unsigned int *p;
/* Primary copy of FAT */
index = clus*3/2; /* 1st 2 sectors of FAT */
p = &FAT[index];
*p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
/* Secondary copy of FAT */
index = clus*3/2 + 512*2; /* Last 2 sectors of FAT */
p = &FAT[index];
*p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
return;
} /* setFATentry */
/********************************************************/
int errorout(errcode)
int errcode;
{
printf("\n ");
switch (errcode) {
case invadr:
printf("* Invalid disk address format!");
break;
case nofixd:
printf("* This function only applies to Floppy Disk Drives!");
break;
default:
printf("* Unknown Error Encountered!");
} /* switch */
printf("\n\n\7");
} /* errorout */
/********************************************************/
int diskerror(intrpt, status)
unsigned int intrpt,status;
{
printf("\n ");
switch (intrpt) {
case 0x25:
case 0x26:
printf("* DOS Disk Read/Write Error!\n");
printf("\t\tCode = %4x\n",status);
break;
case 0x13:
printf("* ROM-BIOS Disk Read/Write Error!\n");
printf("\t\tCode = %2x\n",status);
break;
} /* switch */
printf("\n\n\7");
} /* diskerror */
/********************************************************/
int diskread(drive, dossectr, nsectrs, buffer)
int drive, dossectr, nsectrs;
unsigned char buffer[];
{
struct regval rreg,sreg;
int i;
unsigned flags;
segread(&segs);
for (i=0; i<512; i++) buffer[i] = 0;
sreg.ds = segs.sds;
sreg.cx = nsectrs;
sreg.dx = dossectr;
sreg.bx = buffer;
sreg.ax = drive-1; /* A=0, B=1 */
flags = sysint(0x25,&sreg,&rreg);
if (flags&0x001) diskerror(0x25,rreg.ax);
return( !(flags&0x001) );
} /* diskread */
/********************************************************/
int bdiskread(drive,track,side,sect,nsectrs,buffer)
int drive, track,side,sect,nsectrs;
unsigned char buffer[];
{
struct regval rreg,sreg;
int i;
unsigned flags;
segread(&segs);
for (i=0; i<512; i++) buffer[i] = 0;
sreg.es = segs.sds;
sreg.ax = 0x0200 + nsectrs;
sreg.cx = (track<<8) + sect;
sreg.dx = (side<<8) + (drive-1);
sreg.bx = buffer;
flags = sysint(0x13,&sreg,&rreg);
if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
return( !(flags&0x001) );
} /* bdiskread */
/********************************************************/
int diskwrite(drive, dossectr, nsectrs, buffer)
int drive, dossectr, nsectrs;
unsigned char buffer[];
{
struct regval rreg,sreg;
int i;
unsigned flags;
segread(&segs);
sreg.ds = segs.sds;
sreg.cx = nsectrs;
sreg.dx = dossectr;
sreg.bx = buffer;
sreg.ax = drive-1; /* A=0, B=1 */
flags = sysint(0x26,&sreg,&rreg);
if (flags&0x001) diskerror(0x26,rreg.ax);
return( !(flags&0x001) );
} /* diskwrite */
/********************************************************/
int bdiskwrite(drive,track,side,sect,nsectrs,buffer)
int drive, track,side,sect,nsectrs;
unsigned char buffer[];
{
struct regval rreg,sreg;
int i;
unsigned flags;
segread(&segs);
sreg.es = segs.sds;
sreg.ax = 0x0300 + nsectrs;
sreg.cx = (track<<8) + sect;
sreg.dx = (side<<8) + (drive-1);
sreg.bx = buffer;
flags = sysint(0x13,&sreg,&rreg);
if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
return( !(flags&0x001) );
} /* bdiskwrite */
/********************************************************/
int displayraw(buffer,nsectrs)
unsigned char buffer[];
int nsectrs;
{
int p,i;
char ascstr[80],ch;
for (i=0; i<(512*nsectrs); i++) {
if (!(i%16)) {
if (i) {
printf("|%s|",ascstr);
}
printf("\n%3d: ",i);
ascstr[p=0] = '\0';
}
printf("%2x ",buffer[i]);
ch = (buffer[i]>=' ' && buffer[i]<='~') ? buffer[i] : '.';
ascstr[p++] = ch;
ascstr[p] = '\0';
}
printf("|%s|",ascstr);
printf("\n\n");
} /* displayraw */
/********************************************************/
int homecursor()
{
struct regval rreg,sreg;
sreg.ax = 0x0200; /* cursor position service */
sreg.bx = 0x0000; /* display page number */
sreg.dx = 0x0000; /* row and column position */
sysint(0x10,&sreg,&rreg);
}
/********************************************************/
int clearscreen()
{
struct regval rreg,sreg;
sreg.ax = 0x0600; /* service plus blank code */
sreg.bx = 0x0700; /* bh = attrib byte */
sreg.cx = 0x0000; /* upper left corner of window */
sreg.dx = (24<<8) + 79; /* lower right corner of window */
sysint(0x10,&sreg,&rreg);
homecursor();
}