home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- Program: DEBRAIN
- Date: June 17, 1988
- Descript: Program "cures" diskettes infected with the "Brain" virus.
-
- Language: Turbo C
-
- Operation: Run it by typing: x> DEBRAIN 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.
-
- If it thinks the diskette is infected, then just before the
- cure is effected, a confirmation will be asked for.
- You can leave the diskette infected if desired.
-
-
- The Brain virus appears to have been hacked into a more
- virulent strain by persons unknown... New version should catch
- both strains.
-
- ***************************************************************/
- #include <stdio.h>
- #include <dos.h>
- /* Error Message Definitions */
- #define noarg 1
- #define invadr 2
- #define nofixd 3
-
- /* Misc Definitions */
- #define byte unsigned char
- #define word unsigned int
- #define TRUE 1
- #define FALSE 0
- #define GOOD 1
- #define BAD 0
- #define FOUND_BAD_CLUSTERS 1
-
- char *boot_strings[] = { "Non-System disk or disk error",
- "Replace and strike any key when ready",
- "Disk Boot failure",
- "IBMBIO COMIBMDOS COM" };
-
- int num_boot_strings = 4;
-
- int bogus_clus,
- bogus_side,
- bogus_sect,
- bogus_trk,
- bogus_dls; /* dls = dos logical sector */
-
- int pc_infected=FALSE;
-
- typedef 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; } BiosParmBlock;
-
-
- struct direntry {
- char fname[8];
- char ext[3];
- byte attrib;
- byte resvd[10];
- word xtime;
- word xdate;
- word startFAT;
- long fsize; };
-
- union REGS rreg,sreg;
- struct SREGS segs;
- struct direntry directory[1024];
- int drv;
- unsigned char FAT[10*512]; /* allow for 10 sectors though only 4 */
- /* are needed for D-9 diskettes */
- BiosParmBlock *bootinfo; /* so we can try to work with different types */
- int dispflag= 0;
- /* Assume not Infected */
- int brain_infected = FALSE;
- int infected_bad_secs = FALSE;
- int infected_vol_lab = FALSE;
-
- /* Function Definitions */
- int copyvec();
- int checkvec();
- word gettim();
- word getdat();
- int findlabel();
- int changelabel();
- int getFATentry();
- int setFATentry();
- int dlstoclus();
- int str_scan();
- int errorout();
- int diskerror();
- int diskread();
- int diskwrite();
- int displayraw();
- int homecursor();
- int clearscreen();
- int AbortCure(BiosParmBlock *);
- int checkbootinfo(BiosParmBlock *);
-
- /************************************************************/
- /* Main Program Starts Here */
- /************************************************************/
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int idbyte,sect,i,nsects,dirsize,dirstart;
-
- char drvlet, ans[20];
- unsigned char bufr[1024],bootrec[512],orig_bootrec[512],virus[6*512];
- int bogus_lable = FALSE;
-
- clearscreen();
- printf("Debrain.exe V1.3\n\n");
-
- if (argc<2) {
-
- printf("This program is used to eradicate the Brain virus.\n");
- printf(" Usage: DEBRAIN drive: [ 1 ]\n\n");
- printf(" Where drive is the disk drive containing the infected diskette.\n");
- printf(" And 1 is an optional flag that will dump the sectors to the screen\n\n");
- leave();
-
- } 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");
- leave();
- }
- dispflag = (argc>2);
- }
-
- /* OK lets do some work */
-
- if (pc_infected=((checkvec(0x13)) || (checkvec(0x24)) || (checkvec(0x25)))){
-
- 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");
- leave();
- } /* else */
- } /* if */
-
- printf("\n\nAttempting cure on Drive %c:.... :-)\n",'A'+drv-1);
-
-
- /* 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_lable=findlabel())) {
-
- printf("\n The Virus label was not found on this diskette!\n");
- }
-
- /* Get boot record */
-
- if (dispflag) printf("\nGetting Boot Record...\n");
-
- diskread(drv,0,1,bootrec) ;
-
- if (dispflag) displayraw(bootrec,1);
-
- if ( check_boot_rec( bootrec ) == BAD ){
-
- if ( checkFATpointer( bootrec ) == FOUND_BAD_CLUSTERS ){
-
- if ( dispflag ) printf( "\nGetting original boot record...\n");
-
- diskread( drv, bogus_dls - 1, 1, orig_bootrec );
-
- if (dispflag) displayraw(orig_bootrec,1);
-
- if ( check_boot_rec( orig_bootrec ) == GOOD ) {
-
- /* this is an infected disk... 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");
-
- diskwrite(drv,0,1,orig_bootrec); /* Replace boot rec */
-
- setFATentry(bogus_clus,0); /* Update FAT */
- setFATentry(bogus_clus+1,0);
- setFATentry(bogus_clus+2,0);
-
- diskwrite(drv,1,4,FAT); /* Write updated FAT */
-
- if (bogus_lable) {
- changelabel(bogus_lable);
- diskwrite(drv,dirstart,dirsize,directory); /* Write updated direct */
-
- }
- /* zero out virus sectors */
-
- for(i = 0; i < 512 * 6; i++ ) virus[i] = 0x00;
- diskwrite(drv,bogus_dls-1,6,virus);
- printf("\n\n Your diskette should now be \"cured\"!\n\n");
-
- } else {
- printf("\nOK... Aborting!");
- leave();
- }
- } else { /* can't find good boot rec */
-
- printf("\n\nThis disk appears to be infected by a Brain type virus, but a good");
- printf("\nboot record was not found. ");
- printf("\nSuggest you copy the files that you need (data files only!) and forward");
- printf("\nthis disk to the Computer Science Center.");
- leave();
- }
-
- } else { /* bad boot sector but no virus sectors */
-
- printf("\n\nThis disk does not seem to be infected, but an invalid");
- printf("\nboot record was found.");
- printf("\nThis may be due to a non DOS format program or it is just a bad disk!");
- leave();
- }
-
- }
- else {
- printf("\nThis is a good disk!");
- leave();
- }
- }/* main */
- /********************************************************************/
- leave()
- {
- if (pc_infected) {
- printf("\nREMEMBER! This PC was infected. Be sure to inoculate\n");
- printf(" the vaccine diskette in case it was infected!\n");
- }
- exit();
- }
-
- /***********************************************************************/
-
- checkFATpointer( byte * bootrec )
- {
-
- unsigned int *p,f1,f2,f3;
-
- /* check for brain virus string and confirmation on signature */
-
- p = (unsigned int)&bootrec[4];
- if ( *p != 0x1234 )
- return ( FALSE );
-
- /* this is a Brain Infected Disk */
-
- bogus_side = bootrec[6];
- bogus_sect = bootrec[7];
- bogus_trk = bootrec[8];
-
- bogus_dls = bogus_trk*9*2 + bogus_side*9 + bogus_sect;
-
- /* 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) {
-
- return( FOUND_BAD_CLUSTERS );
- }
- else return (FALSE );
-
-
- }/* checkFATpointer */
-
- /********************************************************/
- 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( 0, 4*vec ); /* check if disk vector was altered */
- vec_cs = peek( 0, 4*vec+2 );
- if (dispflag) printf("vec_cs = %x vec_ip = %x\n", vec_cs, vec_ip);
- if (vec_cs < 0xA000) {
- highmem=peek( 0,0x413); /* check max mem to allow for "funny", */
- /* legitimate disk drivers */
- if (dispflag)printf("highmem = %x\n", highmem );
- 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( 0, 4*src ); /* get original vector */
- vec_cs = peek( 0, 4*src+2 );
- poke( 0, 4*dst, vec_ip );
- poke( 0, 4*dst+2, vec_cs );
- highmem=peek( 0, 0x413 ); /* adjust max mem limit while at it */
- highmem += 7; /* get back 7K virus hid in */
- poke( 0, 0x413, highmem );
- return;
- } /* copyvec */
- /********************************************************/
- int changelabel(entry)
- int entry;
- {
- int i;
- char c;
- char newlabel[11] = " ",*p, ans[80];
- char null_label[] = { 0xe5, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00 };
-
- printf( "\nInput a new volume label:" );
-
- ans[0] = 11; /* max vol lable length */
- cgets( ans );
- strncpy( newlabel, &ans[2], ans[1] );
- if (strlen( newlabel ) > 0){
- 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 = getdat();
- directory[entry].xtime = gettim();
- directory[entry].startFAT = 0;
- directory[entry].fsize = 0L;
- }
- else{
- strcpy( directory[entry].fname, null_label ); /* delete vol lab */
- }
- } /* changelabel */
-
- /********************************************************/
- int findlabel()
- {
- int i;
-
- printf("\nfindlable:");
-
- for (i=0; i<112; i++) { /* max 112 entries in D-9 disk */
- if (!directory[i].fname[0]) break;
- if ( (directory[i].attrib & 0x08) &&
- ( str_scan( directory[i].fname, 12, "Brain ")) ) {
- if (!i) { /* label should not be able to be 1st */
- printf("\nThis should not occur! Label First! Abort!\n");
- leave();
- return( FALSE );/* this is just to get the compiler to shut up */
- }
- return(i);
- } /* if */
- } /* for */
- return(FALSE);
- } /* findlabel */
-
- /********************************************************/
- word gettim()
- {
- word time;
-
- sreg.x.ax = 0x2C00;
- intdos(&sreg,&rreg);
- time = ( ((rreg.x.cx>>8)<<11) | ((rreg.x.cx&0xFF)<<5) | (rreg.x.dx>>9) );
- /* printf("\nch=%d cl=%d dh=%d time=%x\n",
- rreg.x.cx>>8 , rreg.x.cx&0xFF, rreg.x.dx>>8 , time); */
- return(time);
- } /* gettime */
-
- /********************************************************/
-
- word getdat()
- {
- word idate;
-
- sreg.x.ax = 0x2A00;
- intdos(&sreg,&rreg);
- idate = ( ((rreg.x.cx-1980)<<9) | ((rreg.x.dx>>8)<<5) | (rreg.x.dx&0xFF) );
- /* printf("\ncx = %d dx= %x dh= %d dl= %d date= %x \n",
- rreg.x.cx, rreg.x.dx, (rreg.x.dx>>8), (rreg.x.dx&0xFF), idate); */
- return(idate);
- } /* getdate */
-
- /********************************************************/
-
- str_scan( char * start, int len, char * str )
- {
- int found = 0,i = 0;
- char * p = start;
-
- while ( !found ) {
-
- while (( *p != str[ 0 ]) && ( p < (start + len )))
- p++;
- if ( p == start + len ) {
- if (dispflag) printf("Couldn't find string %s\n\r", str );
- return( FALSE );
- }
- while(( *(++p) == str[ ++i ]) && ( i < strlen( str )))
-
- /* empty */ ;
-
- if( i == strlen( str )){
- p = p - ( start + i );
- if (dispflag) printf("Found string \"%s\" at %d (%xH) of sector.\n\r", str, p,p);
- return( TRUE );
- }
- i = 0; /* start scanning again */
- }
- return( FALSE );
- }
-
- /********************************************************/
-
- 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 = (unsigned int *)&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 = (unsigned int *)&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 = (unsigned int *)&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[];
- {
- union REGS rreg,sreg;
- int i;
- unsigned retval;
-
- /* segread(&segs);*/
- for (i=0; i < 512 * nsectrs; i++) buffer[i] = 0;
- /* sreg.x.ds = segs.ds;*/
- sreg.x.cx = nsectrs;
- sreg.x.dx = dossectr;
- sreg.x.bx = buffer;
- sreg.x.ax = drive-1; /* A=0, B=1 */
-
- disklabel:
- retval = int86(0x25,&sreg,&rreg);
- if (rreg.x.cflag !=0x00){
- if ((retval & 0x00ff) == 0x0002) {
- printf("Disk not ready! \n");
- printf("Press any key to continue...\n");
- while (!kbhit());
- getch();
- goto disklabel;
- }
- else{
- diskerror(0x25,retval);
- leave();
- }
- }
- return( !(retval) );
- } /* diskread */
-
- /********************************************************/
-
- /********************************************************/
- int diskwrite(drive, dossectr, nsectrs, buffer)
- int drive, dossectr, nsectrs;
- unsigned char buffer[];
- {
- union REGS rreg,sreg;
- int i;
- unsigned flags;
-
- /* segread(&segs);*/
- /* sreg.x.ds = segs.ds;*/
- sreg.x.cx = nsectrs;
- sreg.x.dx = dossectr;
- sreg.x.bx = buffer;
- sreg.x.ax = drive-1; /* A=0, B=1 */
- flags = int86(0x26,&sreg,&rreg);
- if (flags&0x001) diskerror(0x26,rreg.x.ax);
- return( !(flags&0x001) );
- } /* diskwrite */
-
-
- /********************************************************/
- 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()
- {
- union REGS rreg,sreg;
-
- sreg.x.ax = 0x0200; /* cursor position service */
- sreg.x.bx = 0x0000; /* display page number */
- sreg.x.dx = 0x0000; /* row and column position */
- int86(0x10,&sreg,&rreg);
- }
-
- /********************************************************/
- int clearscreen()
- {
- union REGS rreg,sreg;
-
- sreg.x.ax = 0x0600; /* service plus blank code */
- sreg.x.bx = 0x0700; /* bh = attrib byte */
- sreg.x.cx = 0x0000; /* upper left corner of window */
- sreg.x.dx = (24<<8) + 79; /* lower right corner of window */
- int86(0x10,&sreg,&rreg);
- homecursor();
-
- }
-
- /*************************************************************************/
-
- check_boot_rec( byte * bootrec )
- {
- int i;
-
- if (checkBPB((BiosParmBlock *)bootrec) == BAD)
- return( BAD );
- else {
- for ( i = 0; i < num_boot_strings ; i++)
- if (str_scan(bootrec,512,boot_strings[i])== FALSE)
- return( BAD );
- }
- return( GOOD );
- } /* check Boot rec */
-
-
- /**********************************************************************/
-
- checkBPB( BiosParmBlock *BPB)
- {
-
-
- if (dispflag) printf("Checking boot info...\n");
-
- /* check JMP instruction */
-
- if (( BPB->junk1[0] == 0xe9) ||
- (( BPB->junk1[0] == 0xeb) && (BPB->junk1[2] == 0x90))){
- /* this is good...this is coded weired caus it make more sense
- this way...this is an empty staement */
- if (dispflag) printf("JMP instruction = %x %x %x ... GOOD\n", BPB->junk1[0],
- BPB->junk1[1], BPB->junk1[2]);
- }
- else {
- if (dispflag) printf("JMP instruction = %x %x %x ... BAD\n", BPB->junk1[0],
- BPB->junk1[1], BPB->junk1[2]);
- return( BAD );
- }
- /* check OEM info */
- /*
- put code here
- */
-
- /* check sector size ... has to be greater than 128 */
-
- if ( BPB->sectsize < 128){
- if (dispflag) printf("Sector size = %d (%xH) ... BAD\n", BPB->sectsize, BPB->sectsize );
- return( BAD );
- }
- else {
- if (dispflag) printf("Sector size = %d (%xH) ... GOOD\n", BPB->sectsize, BPB->sectsize );
- }
-
- /* check cluster size ... for floppy 0 < x < 3*/
-
- if (( BPB->clustsize == 0) || ( BPB->clustsize > 2)){
- if (dispflag) printf("Cluster size = %d (%xH) ... BAD\n", BPB->clustsize, BPB->clustsize );
- return( BAD );
- }
- else {
- if (dispflag) printf("Cluster size = %d (%xH) ... GOOD\n", BPB->clustsize, BPB->clustsize );
- }
- /* check number of FATs */
-
- if (( BPB->FATcopies == 0) || ( BPB->FATcopies > 4)){
- if (dispflag) printf("Number of FAT copies = %d ... BAD\n", BPB->FATcopies);
- return( BAD );
- }
- else {
- if (dispflag) printf("Number of FAT copies = %d ... GOOD\n", BPB->FATcopies);
- }
-
- /* check rootdir entries */
-
- if( BPB->rootdirentries < 32 ){
- if (dispflag) printf("Number of root directory entries = %d (%xH) ... BAD\n",
- BPB->rootdirentries, BPB->rootdirentries );
- return( BAD );
- }
- else {
- if (dispflag) printf("Number of root directory entries = %d (%xH) ... GOOD\n",
- BPB->rootdirentries, BPB->rootdirentries );
- }
- /* check media descripter byte */
-
- if ( BPB->idbyte < 0xf0 ){
- if (dispflag) printf("Media descripter byte = %xH ... BAD\n",BPB->idbyte );
- return( BAD );
- }
- else {
- if (dispflag) printf("Media descripter byte = %xH ... GOOD\n",BPB->idbyte );
- }
- /* Hey!! if we made it this far without returning then this should be
- a valid BIOS paramiter Block */
- if (dispflag) printf("Valid Bios parameter Block\n");
-
- return( GOOD );
- }
-
- /**********************************************************************/
-
- AbortCure(BiosParmBlock * BPB)
- {
- if ( checkBPB( BPB ) == GOOD){
- printf("This appeares to be a good disk!\n\n");
- leave();
- }
- else{
- printf("This disk has been corrupted by somthing other than\n");
- printf("the (c) Brain virus!\n");
- printf("\n\nUSE AT YOUR OWN RISK!\n");
- leave();
- }
- }
-