/* VirusX - by Steve Tibbett The complete Virus Elimination System! Please - if you find a new virus, Send me a copy! (And warn me it's on the disk!). I want to keep this program current. (Feel free to put something neat (but not copyrighted) on the disk also! */ /* - Ok, it's not the cleanest code in the world - it was written in two days, for a specific purpose, and it works! */ struct Port *diskport; /* disk's port.*/ struct IOStdReq *diskreq; /* disk's IOStdReq */ int DisksChecked, DisksInstalled, SCAFound; /* for title bar info */ char titlebuffer[80]; /* Who needs includes with Aztec? Everything's precompiled! */ /* Amount of boot code we've got (approx): */ #define BSIZE 40 int ChangeCount[4]; /* TD_CHANGECOUNT for all 4 drives */ int LastSum; /* Used in the checksumming */ int CheckDrives; /* Boolean, from the command line */ int error; /* sort of a temporary variable sort of */ unsigned char diskbuffer[3*512];/* Everything ends up in here. I suppose I should have AllocMem'ed this, but it's SO easy this way */ /* Warning messages. These messages get modified before being displayed (Unless you DO have a DF9:) */ char TEXTPTR[] = "Danger: The disk in DF9: is"; char NBCTEXT[] = "Danger: The disk in DF9: has"; /* This is a byte by byte copy of working boot block code. Check it out if you like. This is what gets written back to the disk when you ask VirusX to fix a disk. */ unsigned char bootblock[] = { 'D', 'O', 'S', 0, 0xc0, 0x20, 0x0f, 0x19, 0, 0, 3, 0x70, 0x43, 0xfa, 0, 0x18, 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68, 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,0,0,0,0,0}; /* for IntuiText's */ char def_font[] ="topaz.font"; struct TextAttr TxtAt_Plain = { (UBYTE *)def_font, 8, FS_NORMAL, FPF_ROMFONT}; /*** Non SCA warning requester IntuiText's ***/ struct IntuiText Body2 = { 0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *)"Nonstandard Boot Code!", NULL }; struct IntuiText Body1 = { 0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2 }; struct IntuiText Pos = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL }; struct IntuiText Neg = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL }; /***** SCA Danger Requester IntuiText's ******/ struct IntuiText SCABody2 = { 0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with an SCA Virus!!", NULL }; struct IntuiText SCABody = { 0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)TEXTPTR, &SCABody2 }; struct IntuiText SCAPos = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL }; struct IntuiText SCANeg = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL }; /***** Write Protect Error Requester IntuiText's ******/ struct IntuiText ERRBody2 = { 0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL }; struct IntuiText ERRBody = { 0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"DISK ERROR: Disk is", &ERRBody2 }; struct IntuiText ERRPos = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL }; struct IntuiText ERRNeg = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL }; /***** Rewrite block? Really? ******/ struct IntuiText REWBody3 = { 0, 1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL }; struct IntuiText REWBody2 = { 0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3}; struct IntuiText REWBody = { 0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"Are you sure you want to", &REWBody2 }; struct IntuiText REWPos = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL }; struct IntuiText REWNeg = { 0, 1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL }; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Window *LittleWindow; struct IntuiMessage *Message; struct RastPort *RP; int Keepgoing; /* a boolean flag. it's false when we want out. */ int Class, Code; /* for storing IntuiNewspaper things. */ int x, y, i; /* left over from my using Basic */ /*** The Newwindow Structure. ***/ char TITLETEXT[] = "VirusX 1.0 by Steve Tibbett"; struct NewWindow NewLittleWindow = { 128, /* Left, Top, Width, Height */ 0, 300, 10, 0, /* Frontpen, Backpen */ 1, DISKINSERTED | CLOSEWINDOW | VANILLAKEY | MOUSEBUTTONS, /* IDCMP Flagz */ WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */ NULL, NULL, TITLETEXT, /* My name. Dont touch it!! */ NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN, }; /*********************Da Beginnin*************************/ main(argc, argv) int argc; char *argv[]; { int OldPri; /* Come on, folks, is intuition never NOT going to be available???? */ IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0); /* If checkdrives is true, later on it means we want to check all the drives with disks in them for viruses. */ CheckDrives = FALSE; if (argc == 0) /* If argc == 0, we're a Workbench deryvatuv */ { CheckDrives = TRUE; /* If we're workbench, we want to check drives */ } else { for (i = 0; i < argc; i++) { if (argv[i][0] == '-') /* if we find a -C, we want CheckDrives */ { if (argv[i][1] == 'c' | argv[i][1] == 'C') CheckDrives = TRUE; }; if (argv[i][0] == '?') /* HELP ME! */ { puts("Usage: VirusX [-C]\n"); puts(" -c checks all drives for Virus upon execution\n"); exit(FALSE); }; }; }; /* Save OldPri so we can restore it later on. We're so nice. */ OldPri = SetTaskPri(FindTask(0), 19); /* and stick us up high. */ diskport = CreatePort(0,0); diskreq = CreateStdIO(diskport); SetUp(); DoLittle(); /* The main loop. Do Little. Ya. */ /* restore priorities to saneness, and take off, eh? */ SetTaskPri(FindTask(0), OldPri); DeletePort(diskport); DeleteStdIO(diskreq); exit(FALSE); } /*********************/ DoLittle() { register int Code; register int Class; /* gee */ register int KG2; /* KeepGoing 2. Another booleean. */ LittleWindow = OpenWindow(&NewLittleWindow); if (LittleWindow == NULL) exit(400L); /* No memory to open little window! */ KG2 = TRUE; RP = LittleWindow->RPort; /* easier than typing Move(LittleWindow->RP... all the time */ if (CheckDrives == TRUE) /* We'll fake it:  Set changecount to 1000, to*/ { /*make people think it's been changed */ for (x = 0; x < 4; x++) ChangeCount[x] = 1000; CheckBlock(); /* CheckBlock() checks boot block for virus. */ CheckDrives = FALSE; /* so we don't do it again */ }; SetAPen(RP, 1); SetBPen(RP, 0); SetDrMd(RP, JAM2); /* ya. JAM 2! Love that name! */ while (KG2 == TRUE) { sprintf(titlebuffer, "VirusX: Disks Checked: %d Disks Installed: %d Viruses Found: %d", DisksChecked, DisksInstalled, SCAFound); SetWindowTitles(LittleWindow, -1, titlebuffer); Message = GetMsg(LittleWindow->UserPort); while (Message == NULL) { /* Lets be nice to other tasks! Ya! */ Wait(1<UserPort->mp_SigBit); Message = GetMsg(LittleWindow->UserPort); }; Class = Message->Class; Code = Message->Code; if (Message != NULL) ReplyMsg(Message); if (Class == CLOSEWINDOW) { CloseWindow(LittleWindow); exit(FALSE); }; if (Class == DISKINSERTED) CheckBlock(); }; /* KG2 = false, we fell thru to here. Ow. */ CloseWindow(LittleWindow); return; } /**********************/ puts(str) /* outputs a string, but is REAL small. */ char *str[]; { Write(Output(), str, strlen(str)); } /********************/ /* Opens trackdisk, finds out who's out there, and sets Changecount up accordioningly. */ /********************/ SetUp() { for (x = 0; x < 4; x++) /* go thru all 4 possible drives */ { ChangeCount[x] = 0; error = OpenDevice("trackdisk.device",x,diskreq,0); if (error > 0) continue; /* no drive here */ diskreq->io_Command = TD_CHANGENUM; error = DoIO(diskreq); ChangeCount[x] = diskreq->io_Actual; /* save changecount for later */ CloseDevice(diskreq); }; } /********************************/ /* This routine returns which drive changed disks lately */ /********************************/ WhoChanged() { int RetVal; /* The value we'll return */ RetVal = -1; /* return -1 if all else fails */ for (x = 0; x < 4; x++) { if (ChangeCount[x] == 0) continue; /* no drive here */ error = OpenDevice("trackdisk.device",x,diskreq,0); if (error > 0) continue; /* no drive here */ diskreq->io_Command = TD_CHANGESTATE; DoIO(diskreq); if (diskreq->io_Actual != 0) { continue; }; diskreq->io_Command = TD_CHANGENUM; DoIO(diskreq); if (diskreq->io_Actual != ChangeCount[x]) { RetVal = x; ChangeCount[x] = diskreq->io_Actual; CloseDevice(diskreq); goto Out; }; CloseDevice(diskreq); }; Out:; return(RetVal); } /********************************/ CheckBlock() { int Sum, Bootable, Virus; /* Virus is a flag, Bootable is a flag, Sum the cksum. */ int a, Unit; int SCA; /* don't get scared, it's just a flag. */ Unit = WhoChanged(); CheckAgainYouFool:; /* oh oh, a label. Could be a goto later on! */ DisksChecked++; SCA = FALSE; /* Unit # to open is returned by "WhoChanged()" up above. */ if (Unit == -1) return; error = OpenDevice("trackdisk.device",Unit,diskreq,0); if (error > 0) return; /* I've heard stories that pulling a read request to block zero with a length of 1024 will cause the virus to write itself back. Not taking any chances. */ diskreq->io_Command = CMD_READ; diskreq->io_Data = diskbuffer; diskreq->io_Length = 3*512; diskreq->io_Offset = 0; DoIO(diskreq); diskreq->io_Length = 0; diskreq->io_Command = TD_MOTOR; DoIO(diskreq); /* turn off motor */ if (diskreq->io_Error > 19) return; /* disk error, lemme out */ CloseDevice(diskreq); Sum = 0; for (a=0; a<1024; a=a+4) { LastSum = Sum; Sum = Sum + diskbuffer[a+3]; Sum = Sum + (diskbuffer[a+2] * 256); Sum = Sum + (diskbuffer[a+1] * 65536); Sum = Sum + (diskbuffer[a] * (65536 * 256)); if (LastSum > Sum) Sum++; /* took me a while to figger this out */ } if (Sum != 0) return; /* if it's not bootable, we DONT want it! */ /* check specifically for SCA virus */ if (diskbuffer[8] == 'C') if (diskbuffer[9] == 'H') if (diskbuffer[10] == 'W') { SCA = TRUE; /* CHW is part of SCA virus */ SCAFound++; }; /* compare boot block with real boot block. If it's not, notify God. */ Virus = FALSE; for (x = 0; x < 39; x++) /* nuum of lements in bootblock */ { if (diskbuffer[8+x] != bootblock[8+x]) { Virus = TRUE; }; }; /* Oh no, a Virus! */ if (Virus == TRUE) { /* Oh no, it's the SCA Virus! */ if (SCA != TRUE) { Delay(1); NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */ error = AutoRequest(LittleWindow, &Body1, &Pos, &Neg, 0, 0, 320, 75); if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */ Delay(1); } else { /* Phew, just a nonstandard boot block, probably */ Delay(1); TEXTPTR[23] = '0'+Unit; error = AutoRequest(LittleWindow, &SCABody, &SCAPos, &SCANeg, 0, 0, 320, 75); if (error == TRUE) DoInstall(Unit); /* user wants it fixed. */ Delay(1); }; }; Unit = WhoChanged(); /* more than one disk was changed. check again */ if (Unit != -1) goto CheckAgainYouFool; } /********************************/ /* This is where the boot code gets changed */ /********************************/ DoInstall(un) int un; /* unit to write to */ { register int x; register int Sum; int err, a; /* Rewrite disk? Really? */ error = AutoRequest(LittleWindow, &REWBody, &REWPos, &REWNeg, 0, 0, 320, 75); if (error != TRUE) return; /* user changed his brain. */ DisksInstalled++; for (x = 0; x < 1024; x++) diskbuffer[x] = 0; /* clear diskbuffer to zero. clean. */ for (x = 0; x < 50; x++) { diskbuffer[x] = bootblock[x]; /* copy boot code into buffer */ }; /* Write it ! */ error = OpenDevice("trackdisk.device", un,diskreq,0); if (error > 0) return; diskreq->io_Command = CMD_READ; diskreq->io_Data = diskbuffer; diskreq->io_Length = 512; diskreq->io_Offset = 44*512; DoIO(diskreq); trygain: /* GOTO! A GOTO! OH NOOOO! */ diskreq->io_Command = TD_PROTSTATUS; DoIO(diskreq); /* check if disk is write protected */ if (diskreq->io_Actual != 0) { error = AutoRequest(LittleWindow, &ERRBody, &ERRPos, &ERRNeg, 0, 0, 320, 75); if (error == TRUE) /* error is true or false, depending on user */ { goto trygain; }; CloseDevice(diskreq); return; /* unrecoverable write protect error!!!!!!!!! */ }; diskreq->io_Length = 1024; /* here we go! */ diskreq->io_Data = &diskbuffer[0]; diskreq->io_Command = CMD_WRITE; diskreq->io_Offset = 0L; DoIO(diskreq); diskreq->io_Command = CMD_UPDATE; /* flush buffer to disk */ DoIO(diskreq); error = diskreq->io_Error; diskreq->io_Length = 0; diskreq->io_Command = ETD_MOTOR; DoIO(diskreq); /* turn off motor */ CloseDevice(diskreq); if (error > 19) { SetWindowTitles(LittleWindow, "Error, Nothing Done.", -1); } else { SetWindowTitles(LittleWindow, "Disk Healed.", -1); }; Delay(100); SetWindowTitles(LittleWindow, TITLETEXT, -1); } /************************/