/************************************************************************/ /* */ /* */ /* 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 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. */ /* 18-Feb-89: And boy, am I tired. 8 (count 'em) 8 new */ /* viruses in this version. Ack! DOUBLE */ /* the last version. New option: CHECK, good */ /* for including VirusX with a commercial */ /* program. V3.20 */ /* */ /************************************************************************/ /* */ /* 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 */ /* - I took this one out. It's not really a */ /* 'Virus' in that it won't overwrite a disk */ /* without asking you first. Besides, it seems */ /* a lot of people LIKE the SystemZ Virus */ /* Protector (though it isn't perfect). */ /* */ /* Lamer Exterminator - THIS one was a bugger. Yet another virus */ /* aimed at hurting people. Y'see, a Lamer */ /* is apparently the worst kind of pirate - */ /* one who doesn't crack software, doesn't */ /* write software, just collects names and */ /* addresses and collects and spreads software. */ /* Lamers don't do anybody any good - and the */ /* guy behind this Virus took it upon himself */ /* to make their (and our) lives miserabler. */ /* Anyway, this virus loads into RAM into a */ /* different location every time (using a */ /* random location). It is encrypted on the */ /* disk so you can't SEE the name of it, and */ /* it never actually SHOWS the name (but it's */ /* definately there). It changes the */ /* encryption key used each time it is written */ /* back to disk. It has a counter and will */ /* wait until the machine has been reset 2 times */ /* OR until 3 disks have been infected, and will */ /* then pick a DATA block (Only a DATA block - */ /* FFS disks are safe, I guess), randomly, and */ /* will write the word 'LAMER!' all through it. */ /* This is obviously not good, and will cause */ /* random disk errors. This is the worst kind */ /* of havoc to wreak on the new user - and this */ /* virus is EVERYWHERE! I've gotten it from 5 */ /* people in the last week alone (all from */ /* different countries! Ack!). Anyways, credit */ /* for being the first with this one is */ /* Christian Schneider. Thanks, Christian! */ /* Might as well break the margin convention here, eh? Anyways, */ /* something else I thought of about this virus: It introduces a NEW */ /* way for a Virus to stay in RAM. Y'see, if ExecBase is okay at */ /* reboot time (Exec keeps a checksum, among other things, and checks */ /* to see if anything has been corrupted quite carefully). Anyways, */ /* if Exec thinks ExecBase is okay, it doesn't bother rebuilding it. */ /* Sooo, this virus sets the SumKickData() vector to point at itself. */ /* Then at Reboot when this vector gets called after reset, the virus */ /* ReInstalls himself. At least this is what I think is happening. */ /* This virus sets up a Resident structure, but never sets the Match */ /* Word - either this means we don't need the MatchWord or it means */ /* his SumKickData() is doing the recovery job - either way, it's */ /* new! 3 points for originality. */ /* */ /* Graffiti - The first virus to come with rotating 3-d graphics! */ /* It's neat - you might want to trigger it (I'm not sure */ /* how) before nuking it. Anyway, this one just sets */ /* CoolCapture(), does something with DoIO() during the */ /* reboot but sets it back to normal before anybody gets */ /* to look at it. Lots of code is taken by the graphics */ /* stuff. I just clear the CoolCapture vector. [yawn] */ /* */ /* Old Northstar - Poof. */ /* */ /* 16 Bit Crew - Well, I didn't actually have to DO anything to get */ /* VirusX to recognize it... because it seems to operate */ /* like the Graffiti Virus. If the 16 bit crew is in */ /* RAM, VirusX will say it removed the Graffiti virus. */ /* Oh well. 8-) */ /* */ /* DiskDoktor - I spent more time on this one than on any other. */ /* Y'see, this virus does lots of things. The first one */ /* for some reason was quite funny to me. heh */ /* What it would do is after you have rebooted 5 times, */ /* each time you reboot after that, the virus would eat */ /* 10K times the total number of reboots - so after */ /* rebooting 10 times, you would be short about 100K. */ /* This virus also starts up another TASK. I'm not */ /* exactly sure when it happens, but another task named */ /* 'clipboard.device' will appear at a priority of -120, */ /* and will continually bash the Virus' vectors into the */ /* Coldcapture, Coolcapture, Warmcapture (which it sets */ /* to $ff000000 just to annoy), and the DoIO() vector. */ /* When I was working on this one, I figured I just had */ /* to restore the old values to the DoIO() vector, but as */ /* soon as I did so, the Virus restored them - and since */ /* I didn't disassemble the entire thing, I didn't realize*/ /* this until I wasted time looking for other faults. */ /* This one also allocates some memory, copies some code */ /* out of Exec into this memory, and executes it. I */ /* never bothered to figure out why - Once it's gone, it's*/ /* gone. */ /* */ /* 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 #include #include #include #include #include #include /* / */ #include /* <-- include files */ #include /* \ */ #include #include #include #include #include #include "virusx.i" /* Virusx.i is an ANSI thing. It's got Protoypes. */ /* (or used to anyway) */ /* Latticeisms */ /* What's that you say? C is hard to read? */ void MemCleanup() {} void RawDoFmt(char *, long *, void (*)(), char*); #pragma syscall RawDoFmt 20a ba9804 void __regargs prbuf(char c); int __regargs sprintf(char *buf, char *ctl, char *args) { RawDoFmt(ctl, (long *)&args, prbuf, buf); return(strlen(buf)); } void __regargs prbuf(char c) {__builtin_emit(0x16c0);} /******************************************************************/ /* In case you're interested, that little mess above is a routine */ /* supplied by John Toebes which changes sprintf() from using the */ /* compiler's library into something that uses the ROM code found */ /* in Kickstart. Sooo, it made VirusX about 1.2K or so smaller!! */ /* Feel free to steal this and use it wherever. However, the new */ /* sprintf function can't handle a lot of things - check the Exec */ /* manual (I believe) for details. Neat formatting here, eh? 8-) */ /******************************************************************/ char WhatHappened; /* huh?? */ /******************************************************************/ /* These string constants are used in multiple places, and thus */ /* save bytes by having only one copy of them. */ /******************************************************************/ char TITLETEXT[] = "VirusX 3.20 by Steve Tibbett"; char TDName[] = "trackdisk.device"; char copystring[] = "(Copy Count on this disk: %ld)"; char ITBodyText[80]; char CaptureStr[] = "Capture is pointing at $"; char text[] = "DF6: Boot Sectors"; 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_LAMER[] = "Lamer Exterminator"; char VN_HCS[] = "H.C.S."; char VN_UFOX[] = "UltraFox"; char VN_DDOC[] = "DiskDoc"; char VN_GRAFFITI[] = "Graffiti"; char VN_Bit16[] = "16 Bit Crew"; char VN_PHANTASM[] = "Phantasmumble"; /* Can't remember the whole name */ char VN_OLDNSTAR[] = "Old Northstar"; /********************************************************************/ /* 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 LamerXCount; int HCSCount; int UFoxCount; int DDocCount; int GRAFFITICount; int Bit16Count; int PhantasmCount; int OldNStarCount; /*******************************************************************/ /* 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 */ long DisksChecked, DisksInstalled; /* for title bar info */ long VirusBase; /* ick, whatta name! */ 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; { if (argc == 3) { NewWindow.LeftEdge = atoi(argv[1]); NewWindow.TopEdge = atoi(argv[2]); }; 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) { /* Okay, okay, it's messy and doesn't close the libraries it opens. Look, if we can't get a measley 1.5K, then the system is probably going to crash before the user finds out what hit him, and he probably won't blame me. */ 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! */ RP = Window->RPort; /* This does some setup stuff, I guess, eh? */ SetUp(); /* Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM. */ CheckMemoryForViruses(); /* Hmmm, wonder what this does. */ CheckMemoryForIRQVirus(); CheckBlock(); if (argc != 2) /* New Feature: Virusx CHECK will only check disks then quit */ DoLittle(); /* The main loop. Do Little. Ya. */ Quitter: if (Window != 0) CloseWindow(Window); if (diskport != 0) DeletePort(diskport); if (diskreq != 0) DeleteStdIO(diskreq); CloseLibrary(GfxBase); /* CloseDoor(DoorBase); CloseLibrary(IntuitionBase); hahah bet I fooled you */ CloseLibrary((struct Library *)ExecBase); FreeMem(diskbuffer, (long)3*512); exit(0); /* DoorBase?? */ } /*********************/ DoLittle() { long Code; /* for storing our IntuiMessage stuff */ long Class; 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(50); 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 (toupper(Code)) { case 'I': if (WindowBig == TRUE) WindowBig = FALSE; else WindowBig = TRUE; if (WindowBig == TRUE) { if (Window->TopEdge > 0) MoveWindow(Window, 0L, (long)-Window->TopEdge); SizeWindow(Window, 0L, 200-(Window->Height)); } else SizeWindow(Window, 0L, -Window->Height + 10); WaitForNewSize(); break; 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(); }; }; } /************************************************/ /* 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, LamerX, HCS; char DDoc, GRAFFITI, Bit16, Phantasm, OldNStar; char UFox; unsigned long *iptr; unsigned long *ptr; char drivename[10]; while ((Unit = WhoChanged()) != -1) { strcpy(drivename, "DF0:"); drivename[2] = '0'+Unit; SCA = FALSE; BBandit = FALSE; Revenge = FALSE; ByteWarrior = FALSE; NorthStar = FALSE; Obelisk = FALSE; Pentagon = FALSE; LamerX = FALSE; UFox = FALSE; HCS = FALSE; DDoc = GRAFFITI = Bit16 = Phantasm = OldNStar = 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; 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[0x43] == 0x40) { PentagonCount++; Pentagon = TRUE; } if (iptr[0x40/4] == 0x13fc00a0) { DDocCount++; DDoc = TRUE; } if (iptr[0x150/4] == 0x000100bf) { GRAFFITICount++; GRAFFITI = TRUE; } if (iptr[0x150/4] == 0x3fff2c78) { Bit16Count++; Bit16 = TRUE; } if (iptr[0x40/4] == 0x4240323c) { PhantasmCount++; Phantasm = TRUE; } if (iptr[0x40/4] == 0x0007ec1a) { OldNStarCount++; OldNStar = TRUE; } if (iptr[0x1d0/4] == 0x83353ef0) /* diskbuffer[0x1d0] == 0x83) if (diskbuffer[0x1d1] == 0x35) if (diskbuffer[0x1d2] == 0x3e) if (diskbuffer[0x1d3] == 0xf0) */ { UFoxCount++; UFox = TRUE; } if (diskbuffer[0x40] == 0x51) if (diskbuffer[0x41] == 0xc8) if (diskbuffer[0x42] == 0xff) if (diskbuffer[0x43] == 0xfc) { HCSCount++; HCS = TRUE; } if (diskbuffer[0x40] == 0x03) if (diskbuffer[0x41] == 0x61) if (diskbuffer[0x42] == 0x34) if (diskbuffer[0x43] == 0x3c) { LamerXCount++; LamerX = 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[0x149] == 0x28) if (diskbuffer[0x14a] == 0x23) if (diskbuffer[0x14b] == 0x7c) { 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, (long)(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, (long)(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 (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 if (LamerX == TRUE) { /* At least these guys are getting creative with their Graphics! */ error = MyRequest(VN_LAMER, 1); } else if (HCS == TRUE) { /* At least these guys are getting creative with their Graphics! */ error = MyRequest(VN_HCS, 1); } else if (UFox == TRUE) { /* yawn */ error = MyRequest(VN_UFOX, 1); } else if (DDoc == TRUE) { /* yawn */ error = MyRequest(VN_DDOC, 1); } else if (GRAFFITI == TRUE) { /* yawn */ error = MyRequest(VN_GRAFFITI, 1); } else if (Bit16 == TRUE) { /* yawn */ error = MyRequest(VN_Bit16, 1); } else if (Phantasm == TRUE) { /* yawn */ error = MyRequest(VN_PHANTASM, 1); } else if (OldNStar == TRUE) { /* yawn */ error = MyRequest(VN_OLDNSTAR, 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, "Disk Error!", (STRPTR)-1); } else { SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1); }; Delay(150L); SetWindowTitles(Window, TITLETEXT, (STRPTR)-1); } /************************/ CheckMemoryForViruses() { unsigned long *TD; unsigned short *wordpointer; unsigned long *LongMemPointer; /* Used for reading FROM memory */ unsigned long *ptr; char linebuffer[80]; char *charpointer; unsigned int x; /**************- Check for Byte Bandit (look at TD Vector) *************/ /* (Byte Bandit isn't at a fixed location. Depends on your RAM. */ /* LongMemPointer = &trackdisk.device */ TD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName); x = (unsigned int) TD; x = x - 0x1c; ptr = (unsigned long *) x; LongMemPointer = (unsigned long *) *ptr; x = (unsigned int) LongMemPointer; x = x - 0x1b8; LongMemPointer = (unsigned long *) x; 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; /* Isn't this code terrible? Ick! */ charpointer[0xb1] = 0x71; /* I didn't know what I was doing when */ charpointer[0x1c2] = 0x60; /* I wrote this. (excuses... 8-) */ 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); }; TD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName); x = (unsigned int) TD; x = x - 0x1c; LongMemPointer = (unsigned long *)x; LongMemPointer = (unsigned long *)LongMemPointer[0]; x = (unsigned int)LongMemPointer; x = x - 0x17c; LongMemPointer = (unsigned long *)x; if (*LongMemPointer == ID_DOS_DISK) /* ptr == VirusBase */ { char *a; long *src, *dest; long *vbase; *LongMemPointer = 0; /* Kill DOS\0 */ vbase = LongMemPointer; /* Disable, then repair vectors. */ Disable(); /* addr of real TD vector */ src = &vbase[0x3a8/4]; a = (char *)ExecBase; a = a - 0x264; dest = (unsigned long *)a; *dest = *src; src = (unsigned long *) &vbase[0x3ac/4]; a = (char *)TD; a = a - 0x1c; dest = (unsigned long *)a; *dest = *src; Enable(); ExecBase->KickTagPtr = 0; /* Sorry, I know it's cruel */ MyRequest(VN_LAMER, 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); }; /******************** See if Graffiti is in RAM ***************************/ if ((long)ExecBase->CoolCapture == (long)0x7ec58) { ExecBase->CoolCapture = 0; MyRequest(VN_GRAFFITI, 2); }; /******************** How about Phantasmumble? ***************************/ if ((long)ExecBase->CoolCapture == (long)0x7ec74) { ExecBase->CoolCapture = 0; MyRequest(VN_PHANTASM, 2); }; /******************** Yoo hoo? HCS? Are you here? ******************/ if ((long)ExecBase->CoolCapture == (long)0x7ec64) { /* You are, you little dickens. */ ExecBase->CoolCapture = 0; /* Scat! */ x = (unsigned int) ExecBase; x = x - 0x1c6; ptr = (unsigned long *)x; LongMemPointer = (unsigned long *)0x7ef9c; *ptr = *LongMemPointer; /* un-Step on DoIO() vector */ MyRequest(VN_HCS, 2); }; /**************************** DiskDoktor? ****************************/ wordpointer = ExecBase->CoolCapture; if (*wordpointer == 0x2c79) { if (wordpointer[3] == 0x203c) { int x; Disable(); x = ExecBase; x = x - 0x1c6; LongMemPointer = (long *)x; wordpointer = (UWORD *)*LongMemPointer; x = (int)wordpointer; x = x + (0x15c); wordpointer = (UWORD *)x; *wordpointer = 0x4e75; x = (int)wordpointer; x = x + 0x1e2; wordpointer = (UWORD *)x; *wordpointer = 0x4e75; x = (int)ExecBase; x = x - 0x1c6; ptr = (long *)x; x = (int)*ptr; x = x + 2; LongMemPointer = (long *)x; *ptr = *LongMemPointer; ExecBase->CoolCapture = 0; ExecBase->ColdCapture = 0; ExecBase->WarmCapture = 0; Enable(); MyRequest(VN_DDOC, 2); }; }; /******************** It's the Australian UltraFox ******************/ if ((long)ExecBase->CoolCapture == (long)0x7ed36) { UWORD *wordptr; ExecBase->CoolCapture = 0; x = (unsigned int) ExecBase; x = x - 0x1c6; ptr = (unsigned long *)x; wordptr = (UWORD *)ptr; if (wordptr[0] == 0x0007) { LongMemPointer = (unsigned long *)0x7eb38; *ptr = *LongMemPointer; /* un-Step on DoIO() vector */ }; MyRequest(VN_UFOX, 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); }; if (ExecBase->CoolCapture != 0) { sprintf(linebuffer, "Cool%s%lx", CaptureStr, ExecBase->CoolCapture); if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0; } if (ExecBase->ColdCapture != 0) { sprintf(linebuffer, "Cold%s%lx", CaptureStr, ExecBase->ColdCapture); if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0; } if (ExecBase->WarmCapture != 0) { sprintf(linebuffer, "Warm%s%lx", 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, 0L); WaitForNewSize(); SetAPen(RP, 0L); RectFill(RP, 2, 12, 278, 167); 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<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, 0L); 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, 420L, 80L)); if (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 420L, 78L)); if (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 420L, 78L)); } /********* DoStats() **********/ DoStats() { char linebuffer[80]; SetAPen(RP, 0L); RectFill(RP, 2L, 11L, 303L, Window->Height-13); SetAPen(RP, 1L); sprintf(linebuffer, " Disks Checked: %ld", DisksChecked); Out(20, linebuffer); sprintf(linebuffer, "Disks Installed: %ld", 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_HCS, HCSCount); PV(133, VN_DDOC, DDocCount); PV(142, VN_GRAFFITI, GRAFFITICount); PV(151, VN_Bit16, Bit16Count); PV(160, VN_PHANTASM, PhantasmCount); PV(169, VN_OLDNSTAR, OldNStarCount); PV(178, VN_UFOX, UFoxCount); PV(187, VN_LAMER, LamerXCount); } /****************** Ok, we're REALLY being chintzy here. */ PV(num, name, howmany) int num; char *name; int howmany; { char linebuffer[80]; sprintf(linebuffer, "%-19s: %ld", 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) { 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) || (chr == 0x0a) || (chr == ';') || (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 { WriteFP(fp, "Error removing virus. Check file.\n"); } }; }; 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 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 */ /* 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); }