Virus Patrol
Volume Number: 5
Issue Number: 2
Column Tag: Advanced Mac'ing
Security Patrol for Viruses 
By Steven Seaquist, Washington, DC
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
Politics of Virus Protection
“SecurityPatrol” is a program I wrote to detect and optionally remove the
“nVIR” and “Scores” viruses (all Macintosh viruses known at the time I wrote it),
plus several other conditions I would find suspicious and would want to be warned
about. This is version 1.1. It’s been tested against live strains of nVIR and Scores. It
contains a code database of “fingerprints” to identify known viruses and detect
alterations of a system’s “good” (trusted) resources by future viruses. [The source
code disk for this month contains the complete library of system resource fingerprints
for Security Patrol. In the interest of space, only a few example fingerprints are
printed in the magazine. -Ed]
It wasn’t coded so much to be “user-friendly”; my main goal was to make it
“security-stubborn”: It’s deliberately not easy to alter its code database of resources.
You have to code them in manually and recompile. To put it another way, the easier it
is for a user to alter the database, the easier it is for a virus to alter the database and
masquerade as something innocuous.
On the other hand, there are advantages to the fact that it’s being published in
source code format. It allows you to re-code it to deal with future viruses and/or to
make it deliberately inconsistent with the published version. (A predictable defense is
generally a weakness to attack.) Another significant advantage is that it inherently
discloses its behavior. Sunlight is a strong disinfectant.
[While Apple Computer cannot and does not endorse anything in this article, it's
publication in MacTutor was of sufficient concern that Scott Boyd, a contributing
editor of MacTutor and a member of Apple's internal virus committee, asked and was
given permission to review the article prior to publication. He indicated Apple's
concern that an article of this sort that points out the system weaknesses can also give
more ammunition to fuel future virsus makers. However, since three books have
recently been published on how to create a computer virus, we feel the cat is out of the
bag anyway so the protection this technology will allow developers is more vital than
ever. Accordingly, we are publishing the article essentially unchanged from the
author's version, except for a couple of places where Steven reveals "chinks in the
armor" of Apple's system software. Scott did allow that many of Steven's techniques
are being used in internal security programs at Apple so we feel this approach has
merit. We invite comment on the problem that Scott and others at Apple must wrestle
with: namely how much information should the public be given on the internal
workings of Apple's system software and it's potential vulnerability to viral
attack.-Ed]
The program sends feedback to the screen and to a report file, but first the user
has to select the report filename with a SFPutFile (Save As) dialog. If AppleTalk is
active, pressing Cancel will cause it to Quit; if it’s not active, pressing Cancel will
cause it to stream the text to a direct-connect ImageWriter on the printer port.
(There’s a bug in TML II that causes WriteLn output to the ImageWriter not to work,
but it’ll be fixed soon. In the meantime, the user can send the report to a file or press
Cancel to avoid creating a report file.) After selecting the report file, the user is
presented with the Main Dialog.
Main Dialog’s “Scope of Work” Buttons
The user may want to patrol only a few files, or all files in a folder, or all files
on several disks bought in a store. Maybe the user doesn’t have any particular files in
mind, but wants to see whether or not any file on a partitioned hard disk is infected.
The program cannot know in advance the scope of work to be done, so it asks the user in
its Main Dialog.
Directories: The program puts up an SFGetFile (Open) dialog to allow the user
to select a file. The program patrols all files under the directory that contains the
selected file. Then, under HFS, it recursively patrols all subdirectories. Then it
returns to the SFGetFile dialog. This process repeats until the user presses the Cancel
button.
Directory: Same as Directories, except that it doesn’t patrol subdirectories.
Everything: The program loops thru all currently mounted volumes and patrols
Directories (plural) on each one starting from the root directory.
Files: The program puts up an SFGetFile dialog to allow the user to select a file,
patrols only that file and returns to the SFGetFile dialog. This process repeats until
the user presses the Cancel button.
Quit: The program prints file and resource totals across all patrols before
returning to the Finder.
User Interface: Options
The Main Dialog also has options the user (usually to get the user’s attention) and
for the programmer (usually to help ease the non-trivial programming burden). Both
kinds are controlled by check boxes.
Await Keypress: When errors are reported, the program pauses until the user
presses a key.
Beep: The program beeps at you when suspicious conditions occur. Complaints
get 1 beep, errors get 2 beeps, viral infections get 3 beeps and aborts get 4 beeps.
(Most aborts are caused by programming errors, but they could also signify that the
program is infected.)
Fingerprint: The program lists the fingerprints of all executable resources it
knows about, except CODEs.
Fingerprint CODEs: The program lists the fingerprints of CODE resources too,
which generates a lot of output.
Long Listing: The program lists all filenames to its report file, not just those
that encountered errors.
Remove Viruses: This is a last resort option for users to recover applications
whose backups and masters are lost or unreadable. There are 3 major reasons why
you might want to direct users not to use it: concern as to your legal liability if it
doesn’t remove the virus properly (or damages uninfected applications), a desire to
encourage the safer method (restoring from backups) so as to limit future headaches,
and the possibility of using the infected disk as evidence in a criminal or civil
prosecution (hard to do if you removed the virus as soon as you saw it).
Trace: The program traces its flow. You may want to turn on Await Keypress to
step thru it slowly.
Program Design
SecurityPatrol was dually developed under MDS-compatible TML Pascal I,
version 2.5 (“TML 2.5”) and MPW-compatible TML Pascal II, version 1.0.2 (“TML
II”). Both versions are on the source code disk, with TML 2.5 filenames ending in
“.Pas” and TMLII filenames ending in “.p”. The TML II files are the ones that appear
in this article.
Major differences: The TML 2.5 version is roughly 50K and 3% faster, can
output to a direct-connect ImageWriter on the printer port and types the report file as
an MDS Edit document. The TML II version is roughly 60K, is much easier to develop
in, has a larger text I/O window on larger monitors and types the report file as an
MPW document.
The program is broken up into 4 major modules: a main program called
SecurityPatrol and 3 UNITs called Globals, MainDlog and Patrol. The TML 2.5
versions of these 4 are 99% source code compatible; they differ only in the USES
statement. In addition, the Globals UNIT of both versions include the
“Fingerprint.ipas” file by means of the {$I} directive; that is, because it’s 100%
source code compatible, it’s shared. The CodeSizeLimits UNIT is incompatible; there
are different versions for TML 2.5 and TML II. Finally, there are BitProcs and
PasLibIntf, which are used only in the TML 2.5 version to maintain source code
compatibility with TML II.
The files were named such that, under TML 2.5, dependency relationships are
properly observed if you simply compile them in alphabetical order. Under TML II,
you can let the TML Project Manager and MPW Make facility handle that for you. (I
edit the SecurityPatrol.Proj file to recompile Globals.p if Fingerprint.ipas has
changed, and to give the Fingerprint and Globals CODE resources the preload and locked
attributes.)
Within each module, the procedures are arranged alphabetically for easy lookup.
Since they aren’t necessarily called in alphabetical order, some routines have to be
declared FORWARD.
As far as conversion to other Pascals is concerned, the following may help: The
OUTPUT in the PROGRAM header is a TML 2.5 convention to tell the compiler that the
program will use WriteLn, etc. TML also defines a Text file variable called OUTPUT
that’s implicitly used by all screen output WriteLn’s, etc, and PasLibIntf procedures.
INC and DEC are built-in functions to increment and decrement a variable by one.
(Both are much faster than an assignment such as x := x + 1 because they generate the
ADDQ and SUBQ instructions.) That’s all I can think of for now.
Program Flow
The MainDlog UNIT generates and maintains the Main Dialog display, keyboard
equivalents and option check boxes internally. It returns to the main program when a
Scope of Work button is pushed.
The SecurityPatrol main program manages program initialization, termination,
text I/O and high-level interface between MainDlog and Patrol: Depending on the Scope
of Work button pushed, it passes off to the proper routine of Patrol.
The Patrol UNIT contains service routines to scan volumes and/or directories.
(It’s been programmed to work under both MFS and HFS, but it hasn’t been tested
under the 64K ROMs.) Its heart and soul is the recursive procedure PatrolDir, which,
at the appropriate times, calls 5 routines in Globals: DirectoryBegins, DirectoryEnds,
PatrolBegins, PatrolEnds and ProcessFile. Another routine in Patrol, called
PatrolFiles (which patrols files manually, a file at a time), also calls those same
routines in Globals.
Globals is the largest UNIT and contains all the basic service routines. The first
4 routines just mentioned are currently given only trivial feedback duties at present.
The 5th one (ProcessFile) is where all the action starts. If the file being processed
contains CODE resources, ProcessFile calls ProcessCodes, which calls
LookForKnownViruses and then looks for anomalies in the CODE 0 jump table. Then,
for every executable resource type it knows about, ProcessFile calls ProcessRsrcs
with the address of a routine to process that resource type. LookForKnownViruses and
ProcessRsrcs call routines in Fingerprint to do resource identification. If the
Fingerprint routines say that a resource is infected, LookForKnownViruses calls a
“Disinfected” routine that knows how to restore the CODE 0 jump table before
removing the infected resource(s); ProcessRsrcs calls RemovedRsrc directly to
remove it.
Fingerprint is where the “code database” of good (trusted) and bad resource
identification resides. A resource’s fingerprint is a set of any tests you desire. In this
article, 3 tests are used as the fingerprint; on the MacTutor source code disk(s), 7
tests. As new viruses are created, Fingerprint is where you would insert new code to
detect them.
Commentary on “CodeSizeLimits.p”
CodeSizeLimits is used by PreprocessSelf in the main program, below. The idea
behind it is to prevent a virus from creating a new CODE resource or imbedding itself
in one of the existing CODE resources.
Since TML II uses the standard MPW Link tool, which creates 9 CODE resources,
the gSizeLimit array is 0..8 and gMaxCode is 8. The size limits for CODEs 1 thru 3
contain a little room for expansion, but not enough for even the tiny nVIR virus to fit