home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-12-28 | 53.4 KB | 1,653 lines |
- /************************************************************************/
- /* */
- /* */
- /* VirusX */
- /* */
- /* by Steve Tibbett */
- /* */
- /* */
- /* 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 on the disk also!) */
- /* */
- /* This version of VirusX is my first done with the Lattice 5.0 */
- /* compiler. The Lattice compiler, with the help of John Toebes, */
- /* gave me an executable almost 4K smaller than the best I could */
- /* get out of Manx. Reason enough for me to switch! */
- /* */
- /* The Makefile included in the "source.zoo" file you should have */
- /* gotten in the VirusX.Zoo file this came from, is set up for the */
- /* MANX Make Utility. Switching to Lattice's LMK should be easy, */
- /* but I've had no reason to. The important thing is the command */
- /* line switches and the BLINK command line. */
- /* */
- /* Thanks to John Toebes for a lot of help getting it going, and */
- /* thanks to Dan James for providing the routine down at the bottom */
- /* that actually takes the IRQ Virus out of executable files. */
- /* */
- /************************************************************************/
- /* */
- /* History: */
- /* -------- */
- /* April '88 or so: V1.0 written and released. */
- /* A few days later: V1.01 released. V1.0 wrote garbage to the */
- /* disk if it was write protected then fixed. */
- /* 27-March-88: V1.2 released. V1.2's purpose in life was */
- /* to deal with the Byte Bandit virus. */
- /* (Actually, it's well after midnight - make */
- /* that March 28th. :) */
- /* 28-March-88: Oops, V1.2 was 3K or so bigger than it needed */
- /* to be. Fix it, release v1.21. */
- /* 15-June-88: V1.3, V1.2 cleaned up and made smaller. */
- /* 8-July-88: V1.4. Revenge virus checking, Viewbooting, */
- /* check for SCA in RAM, more cleaning up. */
- /* 24-July-88: V1.5, only change was the addition of the */
- /* Byte Warrior virus. */
- /* 1-Aug-88: V1.6 (busy week), Dan Mosedale sent me the */
- /* Northstar Virus. Nuked it. */
- /* 18-Aug-88: V1.7 - after 2 weeks off, got the Obelisk */
- /* Softworks crew virus. */
- /* a few days later: V1.71, can't remember why. */
- /* September Sometime: Biggest mistake of my life, released V2.0. */
- /* 3 days later: Bigger mistake: Released V2.01 - which was */
- /* 2.0 with another bug added. Argh. */
- /* 6-Nov-88: Finally got some time to clean things up, */
- /* check out the startup code bugs, clean up the */
- /* docs and source, and release V2.1. There */
- /* haven't been any new viruses in about a month */
- /* now, but I hear one or two are on the way. */
- /* 31-Dec-88: Got the IRQ virus yesterday. Neat one! */
- /* Releasing V3.0 tonite or tomorrow to handle */
- /* it. See description below. */
- /* 04-Jan-89: Got 2 new viruses, released 3.1. */
- /* */
- /************************************************************************/
- /* */
- /* Viruses Dealt With: */
- /* ------------------- */
- /* */
- /* SCA - The SCA is the simplest virus to deal with, */
- /* as it's not actually DOING anything except */
- /* hiding in memory, until you reboot. */
- /* We just look at CoolCapture and fix it to get */
- /* it out of RAM. */
- /* */
- /* Byte Bandit - The Byte Bandit virus takes the DoIO() vector */
- /* and redirects it through itself. Thus, any */
- /* attempt to read or write the boot block (ie, */
- /* AmigaDOS trying to figure out what kind of */
- /* disk it is) results in the BB writing itself */
- /* onto that disk. VirusX couldn't just rewrite */
- /* the boot block, we have to get him out of RAM */
- /* first. This virus also has an interrupt that */
- /* crashes the machine every 5 minutes or so */
- /* after it's infected a few of your disks. Ow. */
- /* It stays in memory not via the Capture */
- /* vectors, but by a Resident module. */
- /* */
- /* Revenge - Basically, a Byte Bandit clone except it will */
- /* bring up an obscene pointer a few minutes */
- /* after you reboot. We treat it much like the */
- /* byte bandit. */
- /* */
- /* Byte Warrior - Jumps right into 1.2 Kickstart. Won't work */
- /* under 1.3. Hangs around via Resident struct, */
- /* doesn't do any damage. */
- /* */
- /* North Star - Like SCA, hangs around via CoolCapture, */
- /* killing CoolCapture kills the North Star. */
- /* */
- /* Obelisk Softworks Crew */
- /* - Hangs around via CoolCapture, also */
- /* watches reads of DoIO() (but doesn't */
- /* infect EVERY disk - onlyt ones you boot */
- /* off of) */
- /* */
- /* IRQ - This is the FIRST Non-Bootblock Virus. */
- /* It copies itself from place to place via the */
- /* first executable program found in your */
- /* startup-sequence. It SetFunction's */
- /* OldOpenLibrary(), has a KickTagPtr, */
- /* and lives in the first hunk of an */
- /* infected program. */
- /* THANKS! to Gary Duncan and Henrik Clausen for */
- /* being the first to send this one to me! */
- /* */
- /* Pentagon Circle - This one looks at the DoIO vector, and has */
- /* a CoolCapture vector. It will write itself */
- /* over any virus inserted, but not onto */
- /* anything else. (Neat idea!). No danger, */
- /* easy to eliminate. Holding left button */
- /* while booting with this one shows different */
- /* screen colour, but doesn't get rid of it. */
- /* Thanks to Bill at CMI (CMI*BILL on Plink) */
- /* for sending me this one! */
- /* */
- /* SystemZ Virus Protector */
- /* - This is another 'virus protector' that */
- /* can write itself to disks. Anything that */
- /* spreads itself, under any name, is a */
- /* virus. Doesn't do anything except during */
- /* a reboot, then examines disks and writes */
- /* over viruses. Again, from CMI*BILL. */
- /* */
- /* Thanks also to Robb Walton for being the first to send one of the */
- /* other ones, (but I can't remember which one anymore... 8-( ) */
- /************************************************************************/
- /* */
- /* Notes on making VirusX yourself: The source is included mainly */
- /* for your perusal, not so that you can modify it and redistribute */
- /* it. I've modified Manx's _main.c module to make the detach */
- /* from the initial CLI work properly. I can't redistribute this */
- /* module since it's copyright manx, so here's VirusX without it. */
- /* It will compile and run, but if you run it from WB, it won't quit. */
- /* The version I've supplied should do everything just fine. */
- /* */
- /************************************************************************/
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <exec/types.h>
- #include <intuition/intuition.h>
- #include <devices/bootblock.h>
- #include <devices/trackdisk.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <pragmas/all.h>
- #include <proto/all.h>
- #include <String.h>
- #include "virusx.i"
-
-
- /* Latticeisms */
- void MemCleanup() {}
-
-
- /********************************************************************/
- /* These string constants are used in multiple places, and thus */
- /* save bytes by having only one copy of them. */
- /********************************************************************/
- char TITLETEXT[] = "VirusX 3.10 by Steve Tibbett";
- char TDName[] = "trackdisk.device";
- char copystring[] = "(Copy Count on this disk: %d)";
- char ITBodyText[80];
- char VN_OBELISK[] = "Obelisk";
- char VN_NORTHSTAR[] = "North Star";
- char VN_SCA[] = "SCA";
- char VN_BYTEBANDIT[] = "Byte Bandit";
- char VN_BYTEWARRIOR[] = "Byte Warrior";
- char VN_REVENGE[] = "Revenge";
- char VN_IRQ[] = "IRQ";
- char VN_PENTAGON[] = "Pentagon Circle";
- char VN_SYSTEMZ[] = "SystemZ";
- char CaptureStr[] = "Capture is pointing at $";
- char text[] = "DF6: Boot Sectors";
-
- #define WIN_SIZE 122L
-
- /* Release Date of this version of VirusX */
- char date[] = "January 4, 1988";
-
-
- /********************************************************************/
- /* These counters are for the Info window, one for each virus. */
- /********************************************************************/
- int ObeliskCount;
- int NorthStarCount;
- int SCACount;
- int ByteBanditCount;
- int ByteWarriorCount;
- int RevengeCount;
- int IRQFound;
- int PentagonCount;
- int SystemZCount;
-
-
- /*******************************************************************/
- /* Miscellaneous variables. */
- /*******************************************************************/
- long ChangeCount[4]; /* TD_CHANGECOUNT for 4 drives */
- long LastSum; /* Used in the checksumming */
- long error; /* sort of a temporary variable */
- char WindowBig; /* TRUE if the window is big */
- struct Port *diskport; /* trackdisk's port. */
- struct IOStdReq *diskreq; /* trackdisk's IOStdReq */
- int DisksChecked, DisksInstalled; /* for title bar info */
- long VirusBase; /* ick, whatta name! */
- char FromCLI; /* True if run from CLI */
- struct Process *Process;
-
- struct IntuitionBase *IntuitionBase; /* For Library Bindings */
- struct GfxBase *GfxBase;
- struct Window *Window;
- struct IntuiMessage *Message;
- struct ExecBase *ExecBase;
-
- struct IOStdReq *TimerReq;
- struct MsgPort *TimerPort;
-
- static long fp;
-
- char Keepgoing; /* A flag. It's false when we want out. */
- long x, y, i; /* Left over from my using Basic */
- char flag; /* Another flag. Lets start our own country. */
- LONG thing1, thing2;
-
- struct NewWindow NewWindow =
- {
- 128,0, 309,10, 0,1,
- DISKINSERTED | CLOSEWINDOW | VANILLAKEY | NEWSIZE | MOUSEBUTTONS, /* IDCMP Flagz */
- WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
- NULL, NULL,TITLETEXT,
- NULL,NULL,0,0,0,0,WBENCHSCREEN,
- };
-
- struct RastPort *RP;
-
- #define BSIZE 40 /* Ha! I'm not telling what this is! */
-
-
- /*******************************************************************/
- /* diskbuffer is where all disk io goes to. it's 3*512 rather */
- /* than 2*512, because I believe one of the viruses watches for */
- /* reads of 1024 bytes, so I'm just being safe. */
- /*******************************************************************/
- UBYTE *diskbuffer;
-
-
- /************************************************************************/
- /* 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"; /* What a waste, eh? */
- char CopyText[40];
-
- /*************************************************************************/
- /* 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, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 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, 0x00, 0x00, 0x00,
- 0x00, 0x00};
-
-
- /********************************************************************/
- /* My intuition defines. There's lots of 'em - theyre self explan.*/
- /********************************************************************/
-
- struct TextAttr TxtAt_Plain =
- {
- "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
- };
-
- /*** Non SCA warning requester IntuiText's ***/
-
- struct IntuiText Body2 =
- {
- 0, 1, JAM2, 20,18, &TxtAt_Plain, "Nonstandard Boot Code!", NULL
- };
-
- struct IntuiText Body1 =
- {
- 0,1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2
- };
-
- /*- This one says "The disk in DFx: is" -*/
-
- struct IntuiText GenericFirstBody =
- {
- 0,1, JAM2, 20,8,&TxtAt_Plain, (UBYTE *)TEXTPTR, 0
- };
-
-
- /***** Generic IntuiTexts used as of V1.7 ******/
-
- struct IntuiText GenericDiskBody =
- {
- 0,1, JAM2, 20,18, &TxtAt_Plain,ITBodyText, &GenericFirstBody
- };
-
- struct IntuiText SCAPos =
- {
- 0,1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL
- };
-
- struct IntuiText Repair =
- {
- 0,1, JAM2, 7,3, &TxtAt_Plain, "Repair it", NULL
- };
-
- struct IntuiText SCANeg =
- {
- 0,1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL
- };
-
- /* Special cases (display copy count) */
-
- /***** BBANDIT Requester IntuiText's ******/
- struct IntuiText BBDiskbody2 =
- {
- 0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
- };
-
- struct IntuiText BBDiskbody =
- {
- 0,1, JAM2, 20,18, &TxtAt_Plain, ITBodyText, &BBDiskbody2
- };
-
- /***** Revenge on Disk Requester IntuiText's ******/
- struct IntuiText RevDiskbody3 =
- {
- 0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
- };
-
- struct IntuiText RevDiskbody =
- {
- 0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3
- };
-
-
- /***** Generic Notice - Removed from Memory ****/
- struct IntuiText GRB3 =
- {
- 0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled. See the", NULL
- };
-
- struct IntuiText GRB2 =
- {
- 0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &GRB3
- };
-
- struct IntuiText GenericRAMBody =
- {
- 0,1, JAM2, 20, 8, &TxtAt_Plain, ITBodyText, &GRB2
- };
-
- struct IntuiText BBMPos =
- {
- 0,1, JAM2, 7, 3, &TxtAt_Plain, " Thanks! ", NULL
- };
-
- struct IntuiText Mem3 =
- {
- 0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "some other utility is the cause of it.", NULL
- };
-
- struct IntuiText Mem2 =
- {
- 0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "This could mean a new Virus is in RAM, or", &Mem3
- };
-
- struct IntuiText Mem1 =
- {
- 0,1, JAM2, 20, 8, &TxtAt_Plain, 0 , &Mem2
- };
-
-
- /***** 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
- };
-
-
- /*********************Da Beginnin*************************/
-
- void main(argc, argv)
- int argc;
- char **argv;
- {
-
- FromCLI = TRUE;
-
- switch (argc)
- {
- case 0:
- FromCLI = FALSE;
- break;
-
- case 3:
- NewWindow.LeftEdge = atoi(argv[1]);
- NewWindow.TopEdge = atoi(argv[2]);
- break;
- };
-
- WindowBig = FALSE;
-
- /* Come on, folks, is intuition ever NOT going to be available???? */
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
-
- /* Same with GfxBase. If GfxBase is gone, we DESERVE to crash. */
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
-
- ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0);
-
- diskbuffer = AllocMem((long)3*512, (long)MEMF_CHIP|MEMF_CLEAR);
- if (diskbuffer == 0)
- {
- exit(10);
- };
-
- /* We use the same port/request through the whole program. Works OK. */
- diskport = CreatePort(0L,0L);
- diskreq = CreateStdIO(diskport);
-
- Window = OpenWindow(&NewWindow);
- if (Window == NULL)
- goto Quitter; /* No memory to open little window! */
-
- Process = (struct Process *)FindTask(0L);
- Process->pr_ConsoleTask = 0;
-
- RP = Window->RPort;
-
- /* This does some setup stuff, I guess, eh? */
- SetUp();
-
- /* Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM. */
- CheckMemoryForViruses();
-
- CheckMemoryForIRQVirus();
-
- CheckBlock();
-
- DoLittle(); /* The main loop. Do Little. Ya. */
-
- Quitter:
- if (diskport != 0) DeletePort(diskport);
- if (diskreq != 0) DeleteStdIO(diskreq);
-
- CloseLibrary(GfxBase);
- CloseLibrary(IntuitionBase);
- CloseLibrary((struct Library *)ExecBase);
- FreeMem(diskbuffer, (long)3*512);
- exit(0);
- }
-
- /*********************/
- DoLittle()
- {
- register long Code; /* for storing our IntuiMessage stuff */
- register long Class;
- register char KG2; /* KeepGoing 2. Another booleean. */
-
- KG2 = TRUE;
-
- SetAPen(RP, 1L);
- SetBPen(RP, 0L);
- SetDrMd(RP, (long)JAM2);
-
- while (KG2 == TRUE)
- {
- Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
- if (Message == 0)
- {
- CheckMemoryForIRQVirus();
- Delay(60);
- continue;
- };
-
- Class = Message->Class;
- Code = Message->Code;
- ReplyMsg((struct Message *)Message);
-
- if (Class == CLOSEWINDOW)
- {
- KG2 = FALSE;
- continue;
- };
-
- if (Class == MOUSEBUTTONS)
- if (Code == MENUDOWN)
- {
- Class = VANILLAKEY;
- Code = 'i';
- }
- else continue;
-
- if (Class == VANILLAKEY)
- {
- char flag;
-
- switch (Code)
- {
- case 'i':
- case 'I':
- if (WindowBig == TRUE) WindowBig = FALSE;
- else WindowBig = TRUE;
-
- if (WindowBig == TRUE)
- {
- if (Window->TopEdge > (180-WIN_SIZE)) MoveWindow(Window, 0L, (long)-Window->TopEdge);
- SizeWindow(Window, 0L, WIN_SIZE);
- } else SizeWindow(Window, 0L, -WIN_SIZE);
-
- WaitForNewSize();
- break;
-
-
- case 'c':
- case 'C':
- for (x=0; x<4; x++) ChangeCount[x] = 10000;
- CheckBlock();
-
- default:
- flag = ShowAscii(Code);
- if (flag == 1) CheckBlock();
- };
- if (WindowBig == TRUE) DoStats();
- };
-
- if (Class == DISKINSERTED)
- {
- CheckBlock();
- if (WindowBig == TRUE) DoStats();
- };
- };
-
- CloseWindow(Window);
- }
-
-
- /************************************************/
- /* Opens trackdisk, finds out who's out there, */
- /* and sets Changecount up accordioningly. */
- /************************************************/
- SetUp()
- {
- long x;
-
- for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
- {
- ChangeCount[x] = 1000;
- error = OpenDevice(TDName,(long)x,diskreq,0L);
- if (error > 0)
- {
- ChangeCount[x] = -1;
- } else CloseDevice(diskreq);
- };
-
- }
-
- /*********************************************************/
- /* This routine returns which drive changed disks lately */
- /*********************************************************/
- WhoChanged()
- {
- char RetVal = -1; /* The value we'll return */
-
- for (x = 0; x < 4; x++)
- {
- if (ChangeCount[x] == -1)
- continue; /* no drive here */
- error = OpenDevice(TDName,(long)x,diskreq,(long)0);
- if (error > 0)
- continue; /* no drive here */
-
- diskreq->io_Command = TD_CHANGESTATE;
- DoIO(diskreq);
- if (diskreq->io_Actual != 0)
- {
- CloseDevice(diskreq);
- continue;
- };
-
- diskreq->io_Command = TD_CHANGENUM;
- DoIO(diskreq);
- if (diskreq->io_Actual != ChangeCount[x])
- {
- RetVal = x;
- ChangeCount[x] = diskreq->io_Actual;
- CloseDevice(diskreq);
- break;
- };
-
- CloseDevice(diskreq);
- };
-
- return(RetVal);
- }
-
- /****************************************************************/
- /* Figures out which drive changed disks (using WhoChanged(), */
- /* And checks it. Calling this after every DISKINSERTED is OK.*/
- /****************************************************************/
- CheckBlock()
- {
- /* How many register vars can I use, anyway? */
- register long Sum, Virus;
- register long a, Unit;
- char SCA, ByteWarrior, Revenge, BBandit;
- char NorthStar, Obelisk, Pentagon, SystemZ;
- register unsigned long *iptr;
- unsigned long *ptr;
- char drivename[10];
-
- while ((Unit = WhoChanged()) != -1)
- {
- sprintf(drivename, "DF%c:", Unit+'0');
-
- SCA = FALSE;
- BBandit = FALSE;
- Revenge = FALSE;
- ByteWarrior = FALSE;
- NorthStar = FALSE;
- Obelisk = FALSE;
- Pentagon = FALSE;
- SystemZ = FALSE;
-
- /* Unit # to open is returned by "WhoChanged()" up above. */
- if (Unit == -1) return;
- error = OpenDevice(TDName,(long)Unit,diskreq,0L);
- if (error > 0) return;
-
- DisksChecked++;
-
- error = ReadBlock();
- CloseDevice(diskreq);
- if (error == FALSE) return;
-
- ptr = (long *)diskbuffer;
- iptr = (long *)diskbuffer;
-
- if (iptr[0] != ID_DOS_DISK) return; /* No DOS/0 */
-
- Sum = 0;
- for (a=0; a<256 /*1024/4 cuz we're dealing with ptr math now*/ ; a++)
- {
- LastSum = Sum;
- Sum = Sum + ptr[a];
- if (LastSum > Sum) Sum++; /* took me a while to figger this out */
- }
-
- if (Sum != 0)
- {
- CheckDriveForIRQ(drivename);
- return; /* if it's not bootable, we DONT want it! */
- };
-
-
- if (diskbuffer[0x40] == 0xff)
- if (diskbuffer[0x41] == 0xa0)
- if (diskbuffer[0x42] == 0x20)
- if (diskbuffer[0x42] == 0x40)
- {
- PentagonCount++;
- Pentagon = TRUE;
- }
-
- if (diskbuffer[0x170] == 0xfe)
- if (diskbuffer[0x171] == 0x3a)
- if (diskbuffer[0x172] == 0x4c)
- if (diskbuffer[0x173] == 0xdf)
- {
- SystemZCount++;
- SystemZ = TRUE;
- }
-
- if (diskbuffer[0x34] == 100)
- if (diskbuffer[0xc4] == 48)
- if (diskbuffer[0xc0] == 68)
- if (diskbuffer[0xf1] == 7)
- {
- ByteWarriorCount++;
- ByteWarrior = TRUE;
- };
-
- if (diskbuffer[0x2b] == '9')
- if (diskbuffer[0x2c] == '.')
- if (diskbuffer[0x2d] == '8')
- if (diskbuffer[0x2e] == '7')
- {
- ByteBanditCount++;
- BBandit = TRUE; /* 9.87 is part of BBandit Virus */
- };
-
- /* 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 */
- SCACount++;
- };
-
- if (diskbuffer[0xe] == 'I')
- if (diskbuffer[0xf] == 'D')
- if (diskbuffer[0x10] == '9')
- if (diskbuffer[0x1a6] == 'f')
- {
- Revenge= TRUE;
- RevengeCount++;
- };
-
- if (diskbuffer[0x12] == 78)
- if (diskbuffer[0x13c] == 68)
- if (diskbuffer[0x18] == 83)
- if (diskbuffer[0x19] == 116)
- {
- NorthStar = TRUE;
- NorthStarCount++;
- };
-
-
- if (diskbuffer[0x38] == 71)
- if (diskbuffer[0xbc] == 83)
- if (diskbuffer[0x1fb] == 100)
- if (diskbuffer[0x2d] == 80)
- {
- Obelisk = TRUE;
- ObeliskCount++;
- };
-
- /* compare boot block with real boot block. If it's not, notify God. */
- Virus = FALSE;
-
- for (x = 0; x < 39; x++) /* num of bytes in bootblock */
- {
- if (diskbuffer[8+x] != bootblock[8+x])
- {
- Virus = TRUE;
- };
- };
-
- /* Oh no, a Virus! */
- if (Virus == TRUE)
- {
- NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
- TEXTPTR[23] = '0'+Unit;
- error = FALSE;
-
- if (SCA == TRUE)
- {
- /* OH NOOOOO, an SCA virus. Wimpo virus, compared to BBandit
- but it's a lot nicer code to read. */
- error = MyRequest(VN_SCA, 1);
- }
- else if (BBandit == TRUE)
- {
- /* The Byte Bandit Virus. Tricky bugger, he WAS. Cheats, tho. */
- sprintf(CopyText, copystring, (diskbuffer[74]*256)+diskbuffer[75]);
- BuildITBodyText(VN_BYTEBANDIT, 1);
- error = AutoRequest(Window, &BBDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
- }
- else if (Revenge == TRUE)
- {
- /* Revenge virus. X rated bugger, lot like Byte Bandit. */
- sprintf(CopyText, copystring, (diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
- BuildITBodyText(VN_REVENGE, 1);
- error = AutoRequest(Window, &RevDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
- }
- else if (ByteWarrior == TRUE)
- {
- /* Byte Warrior. Very 'friendly' virus. Ez to get rid of. */
- error = MyRequest(VN_BYTEWARRIOR, 1);
- }
- else if (Pentagon == TRUE)
- {
- /* Pentagon Circle. An 'AntiVirus', and not a bad one at that. */
- error = MyRequest(VN_PENTAGON, 1);
- }
- else if (SystemZ == TRUE)
- {
- /* SystemZ, Very benign, but it can spread */
- error = MyRequest(VN_SYSTEMZ, 1);
- }
- else if (NorthStar == TRUE)
- {
- /* NorthStar. Nice virus - alerts you to others, ez to get rid of */
- error = MyRequest(VN_NORTHSTAR, 1);
- }
- else if (Obelisk == TRUE)
- {
- /* At least these guys are getting creative with their Graphics! */
- error = MyRequest(VN_OBELISK, 1);
- }
- else
- {
- /* Probably just a custom boot block (or a new virus...) */
- error = AutoRequest(Window, &Body1, &SCAPos, &SCANeg, 0L, 0L, 320L, 70L);
- }
- if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
- };
- CheckDriveForIRQ(drivename);
- }; /* End of While Whochanged */
-
- }
-
- /********************************************/
- /* This is where the boot code gets changed */
- /********************************************/
- DoInstall(un)
- int un; /* unit to write to */
- {
- register int x;
-
- /* Rewrite disk? Really? */
- error = AutoRequest(Window, &REWBody, &REWPos, &REWNeg, 0L, 0L, 320L, 75L);
- if (error != TRUE) return; /* user changed his brain. */
-
- DisksInstalled++;
-
- error = OpenDevice(TDName, (long)un,diskreq,0L);
- if (error > 0) return;
-
- TryGain:
-
- diskreq->io_Command = TD_PROTSTATUS;
- DoIO(diskreq); /* check if disk is write protected */
-
- if (diskreq->io_Actual != 0)
- {
- error = AutoRequest(Window, &ERRBody, &ERRPos, &ERRNeg, 0L, 0L, 280L, 75L);
- if (error == TRUE) /* error is true or false, depending on user */
- {
- goto TryGain;
- };
- CloseDevice(diskreq);
- return; /* unrecoverable write protect error!! Panic!!!!!!! */
- };
-
- for (x = 0; x < 1024; x++)
- diskbuffer[x] = 0; /* clear diskbuffer to zero. clean. */
-
- CopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
-
- /* Write it ! */
-
- error = 0;
- diskreq->io_Length = 1024; /* here we go! */
- diskreq->io_Data = (APTR)diskbuffer;
- diskreq->io_Command = CMD_WRITE;
- diskreq->io_Offset = 0L;
- DoIO(diskreq);
- error = diskreq->io_Error;
-
- if (error < 19)
- {
- diskreq->io_Command = CMD_UPDATE; /* flush buffer to disk */
- DoIO(diskreq);
- error = diskreq->io_Error;
- };
-
- if (error < 19)
- {
- diskreq->io_Length = 0;
- diskreq->io_Command = ETD_MOTOR;
- DoIO(diskreq); /* turn off motor */
- error = diskreq->io_Error;
- };
-
- CloseDevice(diskreq);
-
- if (error > 19)
- {
- SetWindowTitles(Window, "Error, Nothing Done.", (STRPTR)-1);
- }
- else
- {
- SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
- };
-
- Delay(150L);
- SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
- }
-
-
- /************************/
-
- CheckMemoryForViruses()
- {
- long Temp;
- unsigned short *wordpointer;
- unsigned long *LongMemPointer; /* Used for reading FROM memory */
- unsigned long *ptr;
- char linebuffer[80];
- char *charpointer;
-
- /**************- Check for Byte Bandit (look at TD Vector) *************/
- /* (Byte Bandit isn't at a fixed location. Depends on your RAM. */
-
- /* LongMemPointer = &trackdisk.device */
- LongMemPointer = (long *)FindName(&ExecBase->DeviceList, TDName);
- Temp = (long)LongMemPointer;
- Temp = Temp - 0x1c;
- LongMemPointer = (long *)Temp;
- VirusBase = (*LongMemPointer) - 0x1b8;
- LongMemPointer = (unsigned long *)VirusBase;
-
- if (*LongMemPointer == ID_DOS_DISK) /* klugo */
- {
- /* Ok, so we don't really remove it from memory, but we DO render
- it harmless. */
- Disable();
- charpointer = (char *)VirusBase;
- charpointer[0xaa] = 0x4e;
- charpointer[0xac] = 0x4e;
- charpointer[0xae] = 0x4e;
- charpointer[0xb0] = 0x4e;
-
- charpointer[0xab] = 0x71;
- charpointer[0xad] = 0x71;
- charpointer[0xaf] = 0x71;
- charpointer[0xb1] = 0x71;
-
- charpointer[0x1c2] = 0x60;
- charpointer[0x1c3] = 0;
-
- charpointer[0x2d2] = 0x60;
- charpointer[0x2d3] = 0;
-
- charpointer[0x388] = 0x4e;
- charpointer[0x389] = 0x75;
-
- charpointer[0x3ea] = 0;
- charpointer[0x3eb] = 0;
-
- charpointer[0] = 0;
- Enable();
-
- MyRequest(VN_BYTEBANDIT, 2);
- };
-
- /****************- Look for Revenge Virus (at $7e000) ****************/
- if ((unsigned long)ExecBase->CoolCapture == (unsigned long)516192)
- {
- /* Fix the CoolCapture vector */
- ExecBase->CoolCapture = 0;
-
- Disable();
-
- wordpointer = (unsigned short *)(0x7e000);
- wordpointer[0] = 0;
-
- wordpointer = (unsigned short *)(0x7e000+0x1e0);
- wordpointer[0] = 0x4ef9;
- wordpointer[1] = 0x0007;
- wordpointer[2] = 0xe066;
-
- wordpointer = (unsigned short *)0x7e2da;
- wordpointer[0] = 0x4ef9;
- wordpointer[1] = 0x0007;
- wordpointer[2] = 0xe06c;
-
- Enable();
-
- MyRequest(VN_REVENGE, 2);
- };
-
- /******************** See if SCA is in RAM ***************************/
- if ((long)ExecBase->CoolCapture == (long)0x7ec3e)
- {
- ExecBase->CoolCapture = 0;
- MyRequest(VN_SCA, 2);
- };
-
- /***************** Check for Obelisk *******************************/
- if ((APTR)ExecBase->CoolCapture == (APTR)0x7e86c)
- {
- ExecBase->CoolCapture = 0;
- ptr = (unsigned long *)0x7e88a;
- Forbid();
- ptr[0] = 10;
- Permit();
- MyRequest(VN_OBELISK, 2);
- };
-
- /******************** How about North Star? **************************/
- if ((APTR)ExecBase->CoolCapture == (APTR)0x7ec0e)
- {
- ExecBase->CoolCapture = 0;
- MyRequest(VN_NORTHSTAR, 2);
- };
-
- /********************* Check for Byte Warrior ************************/
- wordpointer = (unsigned short *)0x7f800;
- if ( wordpointer[0] == (0x444f) )
- {
- wordpointer = (unsigned short *)0x7f954;
- if (wordpointer[0] == 0x4afc)
- {
- wordpointer[0] = 0; /* Kill resident matchtag */
-
- Forbid();
-
- wordpointer = (unsigned short *)0x7f972;
- wordpointer[0] = 0x4ef9;
- wordpointer[1] = 0x00fc;
- wordpointer[2] = 0x06dc;
-
- wordpointer = (unsigned short *)0x7f800;
- wordpointer[0] = 0;
-
- Permit();
-
- MyRequest(VN_BYTEWARRIOR, 2);
- };
- };
-
- /******************** See if Pentagon is in RAM ***************************/
- if ((long)ExecBase->CoolCapture == (long)0x7fb4c)
- {
- ExecBase->CoolCapture = 0;
-
- /* He sometimes has the DoIO() setfunctioned, I can't figure out
- when, but even if he does, he doesn't do any harm anyway, and
- with CoolCapture set to 0, he'll be gone at next reboot. */
-
- MyRequest(VN_PENTAGON, 2);
- };
-
- /********************* Check for Byte Warrior ************************/
- wordpointer = (unsigned short *)0x7f4e0;
- if ( wordpointer[0] == (0x4afc) )
- {
- if (wordpointer[1] == 0x0007)
- {
- wordpointer[0] = 0;
-
- MyRequest(VN_SYSTEMZ, 2);
- };
- }
-
-
-
- if (ExecBase->CoolCapture != 0)
- {
- sprintf(linebuffer, "Cool%s%x", CaptureStr, ExecBase->CoolCapture);
- if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0;
- }
-
- if (ExecBase->ColdCapture != 0)
- {
- sprintf(linebuffer, "Cold%s%x", CaptureStr, ExecBase->ColdCapture);
- if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0;
- }
-
- if (ExecBase->WarmCapture != 0)
- {
- sprintf(linebuffer, "Warm%s%x", CaptureStr, ExecBase->WarmCapture);
- if (MyRequest(linebuffer, 3) == TRUE) ExecBase->WarmCapture = 0;
- }
-
-
- }
-
-
- /**************************************************************/
- /* This is the routine that displauys a block as ASCII text. */
- /**************************************************************/
- ShowAscii(key)
- long key;
- {
- int drive;
- int x,y;
- int deltax, deltay;
- long a;
- int FLAG=0;
-
- struct RastPort *RP;
- RP = Window->RPort;
-
- drive = key - '0';
-
- if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
-
- error = OpenDevice(TDName,(long)drive,diskreq,0L);
- if (error > 0) return;
-
- error = ReadBlock();
-
- CloseDevice(diskreq);
-
- if (error == FALSE) return;
-
- /* save the amount we moved the window */
- deltax = Window->LeftEdge;
- deltay = Window->TopEdge;
-
- MoveWindow(Window, -deltax, -deltay);
-
- if (WindowBig == FALSE) SizeWindow(Window, 278L, 160L);
- else SizeWindow(Window, 278L, 60L);
-
- WaitForNewSize();
-
- SetAPen(RP, 3L);
- Move(RP, (long)(14+(12*8)), 165L);
- Text(RP, "Block 0", 7L);
- Move(RP, (long)(324+(12*8)), 165L);
- Text(RP, "Block 1", 7L);
- SetAPen(RP, 1L);
-
- text[2] = key;
- SetWindowTitles(Window, text, (STRPTR)-1);
-
- x=0; y=0;
-
- SetAPen(RP, 1L);
- SetDrMd(RP, JAM2);
-
- for (a=0; a<512; a=a+32)
- {
- Move(RP, (long)(10+(x*8)), (long)20+(y*9));
- Text(RP, &diskbuffer[a], 32L);
-
- Move(RP, (long)(320+(x*8)), (long)20+(y*9));
- Text(RP, &diskbuffer[a+512], 32L);
- y++;
- };
-
- Wait(1<<Window->UserPort->mp_SigBit);
- Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
-
- /* If a disk was inserted, we want CheckBlock() to happen later on some time */
- if (Message->Class == DISKINSERTED) FLAG=1;
- ReplyMsg((struct Message *)Message);
-
- if (WindowBig == FALSE)
- SizeWindow(Window, -278L, -160L);
- else SizeWindow(Window, -278L, -60L);
-
- SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
- WaitForNewSize();
-
- /* deltas plus current position, in case dude moved the window */
- MoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
- Delay(2L);
- return(FLAG);
- }
-
-
- /*
- When you do a SizeWindow() command, you have to wait for a NEWSIZE
- IntuiMessage before drawing in it. That's all this routine does.
- */
- WaitForNewSize()
- {
- while (TRUE)
- {
- WaitPort(Window->UserPort);
- Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
- if (Message->Class != NEWSIZE)
- {
- ReplyMsg((struct Message *)Message);
- continue;
- };
- ReplyMsg((struct Message *)Message);
- break;
- };
- }
-
- /*
- type:
-
- 1 == "is infected with the xxxx VIRUS!"
- 2 == "somethin about virus in ram"
- 3 == virus in cold/cool/warm capture
- */
-
- BuildITBodyText(text, type)
- char *text;
- int type;
- {
- switch (type)
- {
- case 1:
- strcpy(ITBodyText, "infected with the `");
- strcat(ITBodyText, text);
- strcat(ITBodyText, "' VIRUS!");
- break;
- case 2:
- strcpy(ITBodyText, "NOTICE: The `");
- strcat(ITBodyText, text);
- strcat(ITBodyText, "' VIRUS was found");
- break;
- };
- }
-
- /***** an attempt to save space *********/
- MyRequest(string, type)
- char *string;
- int type;
- {
- if (type != 3)
- {
- BuildITBodyText(string, type);
- } else
- {
- Mem1.IText = string;
- };
-
- if (type == 1) return(AutoRequest(Window, &GenericDiskBody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L));
- if (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 395L, 78L));
- if (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 395L, 78L));
- }
-
-
- /********* DoStats() **********/
- DoStats()
- {
- char linebuffer[80];
-
- SetAPen(RP, 0L);
- RectFill(RP, 2L, 11L, 303L, (WIN_SIZE + 7));
- SetAPen(RP, 1L);
-
- sprintf(linebuffer, " Disks Checked: %d", DisksChecked);
- Out(20, linebuffer);
-
- sprintf(linebuffer, "Disks Installed: %d", DisksInstalled);
- Out(29, linebuffer);
-
- Out(43, " Viruses Found:");
-
- PV(52, VN_SCA, SCACount);
- PV(61, VN_BYTEBANDIT, ByteBanditCount);
- PV(70, VN_NORTHSTAR, NorthStarCount);
- PV(79, VN_BYTEWARRIOR, ByteWarriorCount);
- PV(88, VN_REVENGE, RevengeCount);
- PV(97, VN_OBELISK, ObeliskCount);
- PV(106, VN_IRQ, IRQFound);
- PV(115, VN_PENTAGON, PentagonCount);
- PV(124, VN_SYSTEMZ, SystemZCount);
- }
-
- /****************** Ok, we're REALLY being chintzy here. */
- PV(num, name, howmany)
- int num;
- char *name;
- int howmany;
- {
- char linebuffer[80];
-
- sprintf(linebuffer, "%-16s: %d", name, howmany);
- Out(num, linebuffer);
- }
-
- /***************************************** Cheap? Me? Nooooo.... */
- /* This will write text to the column number in NUM, the text in Name. */
- /* Or something like that. ********************************************/
- Out(num, name)
- int num;
- char *name;
- {
- int len;
- len = 0;
-
- while (name[len] != 0) len++;
-
- Move(RP, 20L, (long)num);
- Text(RP, name, len);
- }
-
-
- ReadBlock()
- {
- diskreq->io_Command = CMD_READ;
- diskreq->io_Data = (APTR)diskbuffer;
- diskreq->io_Length = 3*512;
- diskreq->io_Offset = 0;
- DoIO(diskreq);
- if (diskreq->io_Error > 0) return(FALSE);
- diskreq->io_Length = 0;
- diskreq->io_Command = TD_MOTOR;
- DoIO(diskreq);
- return(TRUE);
- }
-
- unsigned long *OpenLibVectorPtr;
- unsigned long *EntryForOldOpenLib;
- unsigned long *OldOldOpenLibVector;
-
-
- CheckMemoryForIRQVirus()
- {
- long *Array;
- int Num;
-
- Array = (long *)4;
- Array = (long *)Array[0];
- Num = (int)Array;
- Num = Num - 0x196;
-
- OpenLibVectorPtr = (unsigned long *)Num;
-
- EntryForOldOpenLib = (unsigned long *)OpenLibVectorPtr[0];
- OldOldOpenLibVector = (unsigned long *)(((char *)EntryForOldOpenLib) + 0x12);
-
- if (EntryForOldOpenLib[0] == 0x2f3a0010)
- {
-
- /*
- printf("Setting $%x to $%x\n", OpenLibVectorPtr, OldOldOpenLibVector[0]);
- */
-
- OpenLibVectorPtr[0] = OldOldOpenLibVector[0];
- ExecBase->KickTagPtr = 0;
- MyRequest(VN_IRQ, 2);
- };
- }
-
-
- /********************************/
-
- CheckDriveForIRQ(drivename)
- char *drivename;
- {
- int err;
- char buffer[80];
- char dirbuffer[80];
- char filebuffer[100];
- char tempbuffer[100];
- char FoundInDir;
- char FoundInFname;
- char chr;
- int index;
- char pass;
-
- FoundInDir = FALSE;
- FoundInFname = FALSE;
- filebuffer[0] = 0;
-
- pass = 0;
-
- sprintf(dirbuffer, "%sC/DIR", drivename);
- err = CheckFileForIRQ(dirbuffer,0);
- if (err == 1)
- {
- IRQFound++;
- FoundInDir = TRUE;
- }
- else dirbuffer[0] = 0;
-
-
- index = 0;
-
- sprintf(tempbuffer, "%ss/Startup-Sequence", drivename);
- fp = Open(tempbuffer, MODE_OLDFILE);
- if (fp == 0)
- filebuffer[0] = 0;
- else
- {
- while (TRUE)
- {
- err = Read(fp, &chr, 1);
- if (err == 0) break;
- if (chr == 34) continue;
- if (chr == 0x0a) continue;
- if (chr == ';') continue;
- if (chr == ' ') continue;
- break;
- };
-
- if (err != 0)
- {
- while (TRUE)
- {
- filebuffer[index++] = chr;
- filebuffer[index] = 0;
- err = Read(fp, &chr, 1);
- if (err == 0) break;
- if (chr == 34) break;
- if (chr == 0x0a) break;
- if (chr == ';') break;
- if (chr == 32) break;
- };
- };
-
- Close(fp);
-
- sprintf(buffer, "%s%s", drivename, filebuffer);
-
- err = CheckFileForIRQ(buffer, 0);
- if (err == -1)
- {
- sprintf(buffer, "C:%s", filebuffer);
- err = CheckFileForIRQ(buffer, 0);
- };
-
- strcpy(filebuffer, buffer);
-
- if (err == 1)
- {
- FoundInFname = TRUE;
- IRQFound++;
- }
- else filebuffer[0] = 0;
- };
-
- if (FoundInDir == FALSE && FoundInFname == FALSE) return(0);
-
- WBenchToFront();
- fp = Open("CON:70/20/500/100/VirusX", MODE_NEWFILE);
- if (fp == 0) return(0);
-
- WriteFP(fp, "NOTICE: The IRQ Virus was found on volume ");
- WriteFP(fp, drivename);
- WriteFP(fp, "\n");
-
- while (TRUE)
- {
- if (pass == 0)
- {
- strcpy(tempbuffer, dirbuffer);
- }
- else if (pass == 1)
- {
- strcpy(tempbuffer, filebuffer);
- }
- else if (pass == 2) break;
-
- pass++;
-
- if (tempbuffer[0] == 0) continue;
-
- sprintf(buffer, "\nIn the command: %s\n", tempbuffer);
- WriteFP(fp, buffer);
- WriteFP(fp, "Okay to remove it? [Y]: ");
- Read(fp, buffer, 3);
- if (toupper(buffer[0]) == 'Y')
- {
- err = CheckFileForIRQ(tempbuffer, 1);
- if (err == 1)
- {
- WriteFP(fp, "Virus removed.\n");
- } else
- {
- sprintf(buffer, "Error #%d removing virus. Check file.\n", err);
- WriteFP(fp, buffer);
- }
- };
- };
-
- WriteFP(fp, "\nHit RETURN to continue...");
- Read(fp, buffer, 3);
- Close(fp);
- }
-
- WriteFP(fp, string)
- int fp;
- char *string;
- {
- Write(fp, string, strlen(string));
- }
-
- /********************************/
-
- #define VTAG 0x00000109L
- #define BEGIN OFFSET_BEGINNING
- #define END OFFSET_END
- #define OLD MODE_OLDFILE
- #define NEW MODE_NEWFILE
- #define SLONG ((long)sizeof(long))
- #define OK 1 /* no error */
-
- #define NOFILE -1 /* can't find file */
- #define SEEKERR -2 /* seek error on file */
- #define ALLOCERR -3 /* can't allocate memory */
- #define READERR -4 /* error reading file */
- #define VIRUSNF -5 /* virus not found in file */
- #define WRITERR -6 /* error writing to file */
- #define OPENERR -7 /* error opening file for write */
- #define NOTEXE -8 /* not an executable file */
-
- #define GOTHIM OK /* removed virus from file */
-
- #define VTAG 0x00000109L /* virus hunk length */
- #define VSIG1 0x0000FFFEL /* part of virus signature */
- #define VSIG2 0x61000000L /* part of virus signature */
-
-
- static long inp, *buff, size;
-
- cleanup(val)
- int val;
- {
- if(inp) Close(inp);
- if(buff) FreeMem(buff,size);
- return val;
- }
-
- CheckFileForIRQ(fname, flag)
- char *fname;
- int flag;
- {
-
- int i = 0;
- long fhunk, lhunk, nhunk;
- long tbuff[488/4];
-
- inp = 0L; buff = 0L;
-
- if((inp = Open(fname,OLD)) == 0) /* open the desired file */
- return NOFILE;
-
- Read(inp,(char *)&tbuff[0],487); /* get the first long word */
- if(tbuff[0] != 0x000003F3) /* check for executable file */
- return cleanup(NOTEXE);
-
- if(tbuff[5] != VTAG)
- return cleanup(VIRUSNF);
-
- Seek(inp,0L,END); /* seek to end of file */
- size = Seek(inp,0L,BEGIN); /* rewind the file to get size */
- if(size <= 0L)
- return cleanup(SEEKERR);
-
- if((buff = AllocMem(size,0L)) == 0) /* mem buffer for file */
- return cleanup(ALLOCERR);
-
- if(Read(inp,(char *)&buff[0],size) != size) /* read entire file into buffer */
- return cleanup(READERR);
-
- nhunk = buff[ 2 ]; /* number of hunks in file */
- fhunk = buff[ 3 ]; /* first hunk */
- lhunk = buff[ 4 ]; /* last hunk */
-
- /*
- the IRQ virus inserts his code as the first hunk in the file
- we can find the first hunk in the 6th longword of the file
- */
- /* find the start of the virus hunk */
- while(buff[ i++ ] != 0x000003E9)
- ;
- /*
- The virus checks the first hunk for it's signature to prevent
- reinfecting an already infected program. It actually checks for
- 0xFFFE6100 which is the lower half of a move.m instruction and
- the upper half of a bsr instruction. Here we do the same.
- i points to the virus code hunk length.
- */
- if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
- || ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
- return cleanup(VIRUSNF);
-
- if (flag == 0)
- return cleanup(1);
-
- /*
- close the file and reopen it with write access
- mode NEW will effectivly delete the old file contents so if a
- file error occurs before we finish, the file will be corrupt
- */
- Close(inp);
- if((inp = Open(fname,NEW)) == 0)
- return cleanup(OPENERR);
-
- buff[2] -= 1; buff[4] -= 1; /* readjust program header info */
-
- /* write new header */
- if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
- return cleanup(WRITERR);
-
- if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
- return cleanup(WRITERR);
-
- /*
- subtract length of virus hunk and overhead from file size
- i was calculated earlier
- */
- i = i + 8L + VTAG;
- size = (size/SLONG - i)*SLONG;
-
- /* and write old code out to file, ignoring virus hunk */
- if(Write(inp,(char *)&buff[i],size) != size)
- return cleanup(WRITERR);
-
- /* we're done, the file is clean and intact */
- return cleanup(GOTHIM);
- }
-