home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / virus / nobrain.c < prev    next >
C/C++ Source or Header  |  1994-03-05  |  19KB  |  594 lines

  1. /****************************************************************
  2. Program:   NOBRAIN
  3. Author:    Carl Fussell
  4.            Santa Clara Univ
  5.            CARL@SCU.BITNET
  6. Date:      April 1988
  7. Descript:  Program "cures" diskettes infected with the "Brain" virus.
  8.            Only works for DSDD diskettes (though could be easily
  9.            modified).  But that is all Brain appears to infect at this
  10.            point.
  11. Language:  Computer Innovations  CI86  C Language
  12. Operation: Run it by typing:  x> NOBRAIN  DRV:  [0/1]
  13.            where DRV: is the drive containing the "infected" diskette.
  14.            The option 0 or 1 is for verbose mode where it dumps contents
  15.            of infected sectors, steps being performed, etc. to display.
  16.            If specified and non-zero, verbose occurs.
  17.  
  18.            The program first checks to see if the machine itself is
  19.            infected.  If so, you are asked if you want the machine
  20.            "cleansed".  If yes, it is and the program proceeds.  If no,
  21.            the program aborts.  You cannot leave the machine infected
  22.            but proceed with curing the diskettes.
  23.  
  24.            The program will abort at any time it thinks it has found an
  25.            inconsistancy, ie. some portion that does NOT appear to be
  26.            infected.  The diskette must be "fully infected" before cure will
  27.            take place.  If it thinks the diskette IS fully infected, then
  28.            just before the cure is effected, a confirmation will be asked for.
  29.            You can leave the diskette infected if desired.
  30. DISCLAIMER:
  31.            I claim no responsibility whatsoever for any havoc, damage,
  32.            data loss, or anything else that results from the running of
  33.            this program.  You use it AT YOUR OWN RISK!!  I wrote it to
  34.            solve a problem at our site but make absolutely no guarantee
  35.            (implied or otherwise) as to its operation.  Neither does
  36.            Santa Clara University in any way endorse or support the
  37.            use of this program nor does it assume any responsibility
  38.            for any consequences resulting from the running of this
  39.            program.
  40. ****************************************************************/
  41. #include <stdio.h>
  42.  
  43. /*        Error Message Definitions                   */
  44. #define noarg  1
  45. #define invadr 2
  46. #define nofixd 3
  47.  
  48. /*        Misc Definitions                */
  49. #define byte unsigned char
  50. #define word unsigned int
  51.  
  52. /*        Global Definitions                */
  53. struct regval { unsigned ax,bx,cx,dx,si,di,ds,es; };
  54. struct segval { unsigned scs,sss,sds,ses; } segs;
  55. struct {
  56.     byte junk1[3];
  57.     char sysid[8];
  58.     word sectsize;
  59.     byte clustsize;
  60.     word resvsects;
  61.     byte FATcopies;
  62.     word rootdirentries;
  63.     word totalsects;
  64.     byte idbyte;
  65.     word FATsects;
  66.     word trksects;
  67.     word heads;
  68.     word resvspecial;
  69.     byte remainder[4*512-30]; } bootinfo;
  70.  
  71. struct direntry {
  72.     char fname[8];
  73.     char ext[3];
  74.     byte attrib;
  75.     byte resvd[10];
  76.     word xtime;
  77.     word xdate;
  78.     word startFAT;
  79.     long fsize; };
  80.  
  81. struct regval rreg,sreg;
  82. struct direntry directory[1024];
  83. int drv;
  84. unsigned char FAT[10*512];    /* allow for 10 sectors though only 4 */
  85.                             /* are needed for D-9 diskettes */
  86.  
  87. /*        Function Definitions                        */
  88. int copyvec();
  89. int checkvec();
  90. word gettime();
  91. word getdate();
  92. int findlabel();
  93. int changelabel();
  94. int getFATentry();
  95. int setFATentry();
  96. int dlstoclus();
  97. int infected();
  98. int errorout();
  99. int diskerror();
  100. int diskread();
  101. int bdiskread();
  102. int diskwrite();
  103. int bdiskwrite();
  104. int displayraw();
  105. int homecursor();
  106. int clearscreen();
  107.  
  108. /************************************************************/
  109. /*        Main Program Starts Here            */
  110. /************************************************************/
  111.  
  112. main(argc,argv)
  113.     int argc;
  114.     char *argv[];
  115. {
  116.     int idbyte,sect,i,nsects,done=0,dirsize,dirstart,pc_infected;
  117.     unsigned int *p,bogus_clus,f1,f2,f3;
  118.     char drvlet, ans[20];
  119.     unsigned char bufr[1024],bootrec[512],orig_bootrec[512],virus[6*512];
  120.     int bogus_trk,bogus_sect,bogus_side,bogus_dls,bogus_label,dispflag;
  121.  
  122.     if (argc<2) {
  123.         printf("  This program is used to eradicate the Brain virus.\n");
  124.         printf("    Usage:  NOBRAIN drive:\n\n");
  125.         printf("            Where drive is the disk drive containing the
  126.  infected diskette.\n\n");
  127.         printf("    Warning:  Probably should use this on a healthy diskette.
  128.  It may\n");
  129.         printf("              well corrupt the good diskette!\n\n");
  130.         exit();
  131.     } else {
  132.         drvlet = *argv[1];
  133.         drv = toupper(drvlet) - 'A' + 1;    /* A=1, B=2 */
  134.         if (drv<1 || drv>2) {
  135.             printf("   Error:  Only drive A: or B: may be specified!\n");
  136.             exit();
  137.         }
  138.         dispflag = (argc>2);
  139.     }
  140.  
  141.     clearscreen();
  142.     if (pc_infected=checkvec(0x13)) {
  143.         printf("\nWARNING! This machine has itself been infected and thus\n");
  144.         printf("         so has the \"cure\" diskette in all likelihood.\n");
  145.         printf("         You can proceed but will probably need to
  146.  inoculate\n");
  147.         printf("         the \"cure\" diskette too.\7\n");
  148.         printf("\n      VACCINATE machine itself (Y/N) ?");
  149.         scanf("%s",ans);
  150.         if (toupper(ans[0])=='Y') {
  151.             printf("\n      Inoculating the PC...\n");
  152.             copyvec(0x6D,0x13);
  153.         } else {
  154.             printf("\n   Cannot \"cure\" diskettes on an infected machine...");
  155.             printf("\n   Aborting cure....\n");
  156.             exit();
  157.         } /* else */
  158.     } /* if */
  159.     printf("\n\nAttempting cure on Drive %c:....            :-)\n",'A'+drv-1);
  160. /* Get boot record */
  161.     if (dispflag) printf("\nGetting Boot Record...\n");
  162.     diskread(drv,0,1,bootrec) ;
  163.     if (dispflag) displayraw(bootrec,1);
  164.     if (!infected(bootrec,0x30,"\(c\) 1986 Brain")) {
  165.         printf("\nBoot Record Check:\n");
  166.         printf("\n   This does not appear to be a \"Brain\" infected
  167.  diskette.\n");
  168.         printf("\n   Aborting cure...\n");
  169.         exit();
  170.     }
  171. /* extra confirmation on signature */
  172.     p = &bootrec[4];
  173.     if (*p != 0x1234) {
  174.         printf("\nBoot Record Signature Check:\n");
  175.         printf("\n   This does not appear to be a \"Brain\" infected
  176.  diskette.\n");
  177.         printf("\n   Aborting cure...\n");
  178.         exit();
  179.     }
  180.  
  181.     bogus_side = bootrec[6];
  182.     bogus_sect = bootrec[7];
  183.     bogus_trk = bootrec[8];
  184.     bogus_dls = bogus_trk*9*2 + bogus_side*9 + bogus_sect;
  185.  
  186. /* Get virus sectors */
  187.     if (dispflag) printf("\nGetting virus records...\n");
  188.     diskread(drv,bogus_dls,5,virus);
  189.     if (!infected(virus,342,"\(c\) 1986 Brain")) {
  190.         printf("\nVirus Check:\n");
  191.         printf("\n   This does not appear to be a \"Brain\" infected
  192.  diskette.\n");
  193.         printf("\n   Aborting cure...\n");
  194.         exit();
  195.     }
  196.     if (dispflag) displayraw(virus,5);
  197.  
  198. /* Get original Boot record */
  199.     if (dispflag) printf("\nGetting original boot record...\n");
  200.     diskread(drv,bogus_dls-1,1,orig_bootrec) ;
  201.     if (!infected(orig_bootrec,3,"IBM  ")) {
  202.          printf("\n   This appears to be a partially infected \"Brain\" diskette
  203.  but\n");
  204.         printf("   without a \"healthy\" saved boot record was not found.\n");
  205.         printf("\n   Aborting cure...\n");
  206.         exit();
  207.     }
  208.     if (dispflag) displayraw(orig_bootrec,1);
  209.  
  210. /* Get FAT table read in */
  211.     if (dispflag) printf("\nGetting FAT table...\n");
  212.     diskread(drv,1,4,FAT);
  213.     bogus_clus = dlstoclus(bogus_dls);
  214.     f1 = getFATentry(bogus_clus);
  215.     f2 = getFATentry(bogus_clus+1);
  216.     f3 = getFATentry(bogus_clus+2);
  217.     if (dispflag) {
  218.         printf("   Bogus DLS = %d (%XH)\n",bogus_dls,bogus_dls);
  219.         printf("   FAT entry for cluster %d (%xH) = %d (%xH)\n",
  220.             bogus_clus,bogus_clus,f1,f1);
  221.         printf("   FAT entry for cluster %d (%xH) = %d (%xH)\n",
  222.             bogus_clus+1,bogus_clus+1,f2,f2);
  223.         printf("   FAT entry for cluster %d (%xH) = %d (%xH)\n",
  224.             bogus_clus+2,bogus_clus+2,f3,f3);
  225.     }
  226.     if (f1!=0xFF7 || f2!=0xFF7 || f3!=0xFF7) {
  227.          printf("\n   This appears to be a partially infected \"Brain\" diskette
  228.  but\n");
  229.         printf("   FAT virus clusters were not all marked as bad.\n");
  230.         printf("\n   Aborting cure...\n");
  231.         exit();
  232.     }
  233.  
  234. /* Get directory table */
  235.     if (dispflag) printf("\nGetting directory entry...\n");
  236.     dirstart = 1 + 4;        /* boot sector + FAT size */
  237.     dirsize = 7;            /* D-9 diskettes have 7 sectors of dir entries */
  238.     diskread(drv,dirstart,dirsize,directory);
  239.     if (!(bogus_label=findlabel())) {
  240.         printf("\n   The Virus label was not found on this diskette!\n");
  241.     }
  242.  
  243. /* Repair everything */
  244.     printf("\nThis appears to be an infected diskette. \n\n");
  245.     printf("   VACCINATE it (Y/N) ?");
  246.     scanf("%s",ans);
  247.     if (toupper(ans[0])=='Y') {
  248.         printf("\n      Inoculating the Drive...\n");
  249.         setFATentry(bogus_clus,0);                    /* Update FAT */
  250.         setFATentry(bogus_clus+1,0);
  251.         setFATentry(bogus_clus+2,0);
  252.         changelabel(bogus_label);
  253.  
  254.         diskwrite(drv,0,1,orig_bootrec);            /* Replace boot rec */
  255.         diskwrite(drv,dirstart,dirsize,directory);    /* Write updated direct */
  256.         diskwrite(drv,1,4,FAT);                        /* Write updated FAT */
  257.     } else {
  258.         printf("\nOK...  Aborting!");
  259.         exit();
  260.     }
  261.  
  262.     printf("\n\n     Your diskette should now be \"cured\"!\7\n\n");
  263.     if (pc_infected) {
  264.         printf("\nREMEMBER!   This PC was infected.  Be sure to inoculate\n");
  265.         printf("            the vaccine diskette in case it was infected!\n");
  266.     }
  267. } /* main */
  268.  
  269. /********************************************************/
  270. int checkvec(vec)
  271.     int vec;
  272. {
  273.     unsigned int vec_ip,vec_cs,orgvec_ip,orgvec_cs,highmem;
  274.     int bad, mem;
  275.  
  276.     bad = 0;                        /* assume "good" to start */
  277.     vec_ip = peek(4*vec,0);            /* check if disk vector was altered */
  278.     vec_cs = peek(4*vec+2,0);
  279.     if (vec_cs < 0xA000) {
  280.         highmem=peek(0x413,0);        /* check max mem to allow for "funny", */
  281.                                     /* legitimate disk drivers */
  282.         for (mem=64,bad=0; mem<=640; mem+=64) {
  283.             if (highmem==(mem-7)) {
  284.                 bad=1;                /* if max mem value off by 7K => bad */
  285.                 break;
  286.             } /* if */
  287.         } /* for */
  288.     } /* if */
  289.     return(bad);
  290. } /* checkvec */
  291.  
  292. /********************************************************/
  293. int copyvec(src,dst)
  294.     int src;
  295.     int dst;
  296. {
  297.     word vec_ip,vec_cs,highmem;
  298.  
  299.     vec_ip = peek(4*src,0);        /* get original vector */
  300.     vec_cs = peek(4*src+2,0);
  301.     pokew(4*dst,0,vec_ip);
  302.     pokew(4*dst+2,0,vec_cs);
  303.     highmem=peek(0x413,0);        /* adjust max mem limit while at it */
  304.     highmem += 7;                /* get back 7K virus hid in */
  305.     pokew(0x413,0,highmem);
  306.     return;
  307. } /* copyvec */
  308. /********************************************************/
  309. int changelabel(entry)
  310.     int entry;
  311. {
  312.     int i;
  313.     char *newlabel="Brain Dead ",*p;
  314.  
  315.     for (i=0,p=newlabel; i<11; i++)
  316.         directory[entry].fname[i] = *(p+i);
  317.     directory[entry].attrib = 8;
  318.     for (i=0; i<10; i++) directory[entry].resvd[i] = 0;
  319.     directory[entry].xdate = getdate();
  320.     directory[entry].xtime = gettime();
  321.     directory[entry].startFAT = 0;
  322.     directory[entry].fsize = 0L;
  323. } /* deletelabel */
  324.  
  325. /********************************************************/
  326. int findlabel()
  327. {
  328.     int i;
  329.  
  330.     for (i=0; i<112; i++) {                    /* max 112 entries in D-9 disk */
  331.         if (!directory[i].fname[0]) break;
  332.         if (   (directory[i].attrib & 0x08) &&
  333.                (infected(directory[i].fname,0," (c) Brain ")) ) {
  334.              if (!i) {            /* label should not be able to be 1st */
  335.                  printf("\nThis should not occur!  Label First!  Abort!\n");
  336.                  exit();
  337.              }
  338.              return(i);
  339.         } /* if */
  340.     } /* for */
  341.     return(0);
  342. } /* findlabel */
  343.  
  344. /********************************************************/
  345. word gettime()
  346. {
  347.     word time;
  348.  
  349.     sreg.ax = 0x2C00;
  350.     sysint21(&sreg,&rreg);
  351.     time = ( ((rreg.cx>>8)<<11) | ((rreg.cx&0xFF)<<5) | (rreg.dx>>9) );
  352. /*    printf("\nch=%d   cl=%d   dh=%d   time=%x\n",
  353.         rreg.cx>>8 , rreg.cx&0xFF, rreg.dx>>8 , time); */
  354.     return(time);
  355. } /* gettime */
  356.  
  357. /********************************************************/
  358. word getdate()
  359. {
  360.     word idate;
  361.  
  362.     sreg.ax = 0x2A00;
  363.     sysint21(&sreg,&rreg);
  364.     idate = ( ((rreg.cx-1980)<<9) | ((rreg.dx>>8)<<5) | (rreg.dx&0xFF) );
  365. /*    printf("\ncx = %d   dx= %x    dh= %d   dl= %d    date= %x \n",
  366.         rreg.cx, rreg.dx, (rreg.dx>>8), (rreg.dx&0xFF), idate); */
  367.     return(idate);
  368. } /* getdate */
  369.  
  370. /********************************************************/
  371. int infected(tgt,pos,src)
  372.     char *tgt;
  373.     int  pos;
  374.     char *src;
  375. {
  376.     char *p,*q;
  377.     int mismatch,len;
  378.  
  379.     len = strlen(src);
  380.     for (mismatch=0,p=tgt+pos,q=src;  p<tgt+pos+len && !mismatch; p++,q++)
  381.         mismatch = (*p != *q);
  382.     return(!mismatch);
  383. } /* infected */
  384.  
  385. /********************************************************/
  386. int dlstoclus(dls)
  387.     int dls;
  388. {
  389.     return(dls/2-4);
  390. } /* dlstoclus */
  391.  
  392. /********************************************************/
  393. int getFATentry(clus)
  394.     int clus;
  395. {
  396.     int index,entry;
  397.     unsigned int *p;
  398.  
  399.     index = clus*3/2;
  400.     p = &FAT[index];
  401.     entry = (clus%2)? *p >> 4 : *p & 0xFFF;
  402.     return(entry);
  403. } /* getFATentry */
  404.  
  405. /********************************************************/
  406. int setFATentry(clus,val)
  407.     int clus;
  408.     unsigned int val;
  409. {
  410.     int index,entry;                /* On a D-9 diskette, FAT is 4 sectors */
  411.     unsigned int *p;
  412.  
  413. /* Primary copy of FAT */
  414.     index = clus*3/2;                /* 1st 2 sectors of FAT */
  415.     p = &FAT[index];
  416.     *p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
  417.  
  418. /* Secondary copy of FAT */
  419.     index = clus*3/2 + 512*2;        /* Last 2 sectors of FAT */
  420.     p = &FAT[index];
  421.     *p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
  422.  
  423.     return;
  424. } /* setFATentry */
  425.  
  426. /********************************************************/
  427. int errorout(errcode)
  428.    int errcode;
  429. {
  430.    printf("\n    ");
  431.    switch (errcode) {
  432.       case invadr:
  433.              printf("* Invalid disk address format!");
  434.        break;
  435.       case nofixd:
  436.              printf("* This function only applies to Floppy Disk Drives!");
  437.        break;
  438.       default:
  439.              printf("* Unknown Error Encountered!");
  440.    } /* switch */
  441.    printf("\n\n\7");
  442. } /* errorout */
  443.  
  444. /********************************************************/
  445. int diskerror(intrpt, status)
  446.     unsigned int intrpt,status;
  447. {
  448.     printf("\n    ");
  449.     switch (intrpt) {
  450.     case 0x25:
  451.     case 0x26:
  452.         printf("* DOS Disk Read/Write Error!\n");
  453.         printf("\t\tCode = %4x\n",status);
  454.             break;
  455.     case 0x13:
  456.         printf("* ROM-BIOS Disk Read/Write Error!\n");
  457.         printf("\t\tCode = %2x\n",status);
  458.             break;
  459.     } /* switch */
  460.     printf("\n\n\7");
  461. } /* diskerror */
  462.  
  463. /********************************************************/
  464. int diskread(drive, dossectr, nsectrs, buffer)
  465.     int drive, dossectr, nsectrs;
  466.     unsigned char buffer[];
  467. {
  468.     struct regval rreg,sreg;
  469.     int i;
  470.     unsigned flags;
  471.  
  472.     segread(&segs);
  473.     for (i=0; i<512; i++) buffer[i] = 0;
  474.     sreg.ds = segs.sds;
  475.     sreg.cx = nsectrs;
  476.     sreg.dx = dossectr;
  477.     sreg.bx = buffer;
  478.     sreg.ax = drive-1;                    /* A=0, B=1 */
  479.     flags = sysint(0x25,&sreg,&rreg);
  480.     if (flags&0x001) diskerror(0x25,rreg.ax);
  481.     return( !(flags&0x001) );
  482. } /* diskread */
  483.  
  484. /********************************************************/
  485. int bdiskread(drive,track,side,sect,nsectrs,buffer)
  486.     int drive, track,side,sect,nsectrs;
  487.     unsigned char buffer[];
  488. {
  489.     struct regval rreg,sreg;
  490.     int i;
  491.     unsigned flags;
  492.  
  493.     segread(&segs);
  494.     for (i=0; i<512; i++) buffer[i] = 0;
  495.     sreg.es = segs.sds;
  496.     sreg.ax = 0x0200 + nsectrs;
  497.     sreg.cx = (track<<8) + sect;
  498.     sreg.dx = (side<<8) + (drive-1);
  499.     sreg.bx = buffer;
  500.     flags = sysint(0x13,&sreg,&rreg);
  501.     if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
  502.     return( !(flags&0x001) );
  503. } /* bdiskread */
  504.  
  505. /********************************************************/
  506. int diskwrite(drive, dossectr, nsectrs, buffer)
  507.     int drive, dossectr, nsectrs;
  508.     unsigned char buffer[];
  509. {
  510.     struct regval rreg,sreg;
  511.     int i;
  512.     unsigned flags;
  513.  
  514.     segread(&segs);
  515.     sreg.ds = segs.sds;
  516.     sreg.cx = nsectrs;
  517.     sreg.dx = dossectr;
  518.     sreg.bx = buffer;
  519.     sreg.ax = drive-1;                    /* A=0, B=1 */
  520.     flags = sysint(0x26,&sreg,&rreg);
  521.     if (flags&0x001) diskerror(0x26,rreg.ax);
  522.     return( !(flags&0x001) );
  523. } /* diskwrite */
  524.  
  525. /********************************************************/
  526. int bdiskwrite(drive,track,side,sect,nsectrs,buffer)
  527.     int drive, track,side,sect,nsectrs;
  528.     unsigned char buffer[];
  529. {
  530.     struct regval rreg,sreg;
  531.     int i;
  532.     unsigned flags;
  533.  
  534.     segread(&segs);
  535.     sreg.es = segs.sds;
  536.     sreg.ax = 0x0300 + nsectrs;
  537.     sreg.cx = (track<<8) + sect;
  538.     sreg.dx = (side<<8) + (drive-1);
  539.     sreg.bx = buffer;
  540.     flags = sysint(0x13,&sreg,&rreg);
  541.     if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
  542.     return( !(flags&0x001) );
  543. } /* bdiskwrite */
  544.  
  545. /********************************************************/
  546. int displayraw(buffer,nsectrs)
  547.     unsigned char buffer[];
  548.     int nsectrs;
  549. {
  550.     int p,i;
  551.     char ascstr[80],ch;
  552.  
  553.     for (i=0; i<(512*nsectrs); i++) {
  554.         if (!(i%16)) {
  555.         if (i) {
  556.                 printf("|%s|",ascstr);
  557.         }
  558.         printf("\n%3d: ",i);
  559.         ascstr[p=0] = '\0';
  560.     }
  561.  
  562.     printf("%2x ",buffer[i]);
  563.     ch = (buffer[i]>=' ' && buffer[i]<='~') ? buffer[i] : '.';
  564.     ascstr[p++] = ch;
  565.     ascstr[p] = '\0';
  566.     }
  567.     printf("|%s|",ascstr);
  568.     printf("\n\n");
  569. } /* displayraw */
  570.  
  571. /********************************************************/
  572. int homecursor()
  573. {
  574.     struct regval rreg,sreg;
  575.  
  576.     sreg.ax = 0x0200;        /* cursor position service */
  577.     sreg.bx = 0x0000;        /* display page number */
  578.     sreg.dx = 0x0000;        /* row and column position */
  579.     sysint(0x10,&sreg,&rreg);
  580. }
  581.  
  582. /********************************************************/
  583. int clearscreen()
  584. {
  585.     struct regval rreg,sreg;
  586.  
  587.     sreg.ax = 0x0600;        /* service plus blank code */
  588.     sreg.bx = 0x0700;        /* bh = attrib byte */
  589.     sreg.cx = 0x0000;        /* upper left corner of window */
  590.     sreg.dx = (24<<8) + 79;    /* lower right corner of window */
  591.     sysint(0x10,&sreg,&rreg);
  592.     homecursor();
  593. }
  594.