Virus Scout
Volume Number: 7
Issue Number: 1
Column Tag: Programmer's Forum
Virus Scout
By David T. Craig, Kansas City, MO
A Simple Macintosh Virus Scout Pascal Unit
In the past year the Apple Macintosh computer has become plagued by viruses.
My work place was struck twice by a virus last year. As a Macintosh programmer I
became determined to provide a software solution to this growing problem. My solution
is called the Virus Scout, a Pascal unit that attempts to detect the existence of several
viruses in either an application or the System file.
Virus Scout is a very simple anti-virus unit written in MPW Pascal. It should
easily be portable to other Macintosh Pascal compilers such as Think Pascal. Virus
Scout attempts to detect the following viruses:
Scores nVIR Hpat AIDS MEV# INIT29 JUDE
The viruses ANTI and MacMag are listed in the unit source but are not detected
since I don’t have any technical information on how to detect them. Once Virus Scout
has detected a virus you should immediately run one of the many virus buster
programs. I prefer Disinfectant since it appears to do a through job.
Using Virus Scout is very simple from an application. Once compiled and linked
to your application you may call its single entry point:
{1}
FUNCTION Virus_Found (VAR vTypes : gt_VirusTypes) : BOOLEAN;
The Virus_Found function returns TRUE if at least one virus was found in either
the application or the System file. The vTypes parameter is a record of booleans each
corresponding to a virus type. Your program should call Virus_Found shortly after
starting and if a virus was found you should display a dialog and immediately quit to the
Finder. Refer to the source code for the methods used to detect a virus.
Virus Scout is only a beginning in the fight against Macintosh viruses. I hope
other programmers will extend my Virus Scout to detect more viruses and hopefully
even eradicate them.
Listing 1: Virus_Scout.p
{ ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
• MODULE ..... Virus Scout
• DATE ....... June 1990
• AUTHOR ..... David T. Craig
• ADDRESS .... 9939 Locust # 4013, Kansas City, MO 64131
• LANGUAGE ... Apple MPW Pascal 3.0
• COMPUTER ... Apple Macintosh
••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••
• FILE INFORMATION:
• This file contains a very simple virus detection routine. This
routine attempts to detect the following viri:
• Scores nVIR Hpat AIDS MEV# INIT29 ANTI MacMag JUDE
• If one of these viri is found, then a flag is set in the output
parameter for the particular virus.
• Refer to the superb Disinfectant program and its documentation
for the details behind Macintosh viri.
• Note: Viri ANTI and MacMag are not detected since I don't have
any technical information on how to detect them.
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
UNIT Virus_Scout;
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
INTERFACE
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
USES
MemTypes, QuickDraw, OSIntf, OSUtils, ToolIntf, PackIntf, Traps,
Printing, Picker, Perf, PasLibIntf;
{$S SgVirusScout}
TYPE
gt_VirusTypes = PACKED RECORD
virus_Scores : BOOLEAN;
virus_nVir : BOOLEAN;
virus_Hpat : BOOLEAN;
virus_AIDS : BOOLEAN;
virus_MEV : BOOLEAN;
virus_INIT29 : BOOLEAN;
virus_ANTI : BOOLEAN;
virus_MacMag : BOOLEAN;
virus_JUDE : BOOLEAN;
END;
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••
• Routine : Virus_Found
• Purpose : Test if any viri exist within the program or system
file
• Input : (none)
• Output : Virus_Found - True --> virus was found in program or
system
• vTypes - types of found viri
• Notes : Reference: Disinfectant 1.1 documentation (April 16,
1989)
•••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
FUNCTION Virus_Found (VAR vTypes : gt_VirusTypes) : BOOLEAN;
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
IMPLEMENTATION
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{$R+ } { enable range checking }
{$D+ } { place debugger symbols in object code }
{$MC68020-} { always produce plain 68000 code here }
{ ••••••••••••••••••••••••••••••••••••••••••••••••••••••
• Routine : Virus_Found
•••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
FUNCTION Virus_Found (VAR vTypes : gt_VirusTypes) : BOOLEAN;
VAR
sob_virus : BOOLEAN; { virus found flag }
res_count : INTEGER; { resource type count }
res_handle : Handle; { resource data handle }
machine_info : SysEnvRec; { machine low-level info }
finder_info : FInfo; { Finder info for a file }
vf_error : gt_Error; { error result }
BEGIN { ------ Virus_Found ------ }
{ fetch the volume refnum for the Macintosh System Folder }
vf_error := SysEnvirons(1,machine_info);
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ Scores virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find file "Scores" or "Desktop " in System Folder] }

vf_error := GetFInfo('Scores',machine_info.SysVRefNum, finder_info);
vTypes.virus_Scores := (vf_error = NoErr);
IF vTypes.virus_Scores = FALSE THEN
BEGIN
vf_error := GetFInfo('Desktop
',machine_info.SysVRefNum, finder_info);
vTypes.virus_Scores := (vf_error = NoErr);
END;

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ nVir virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "nVIR" resource in app or System File] }
res_count := CountResources('nVIR');
vTypes.virus_nVir := (res_count > 0);

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ JUDE virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "JUDE" resource in app or System File] }
res_count := CountResources('JUDE');
vTypes.virus_JUDE := (res_count > 0);
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ Hpat virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "Hpat" resource] }
res_count := CountResources('Hpat');
vTypes.virus_Hpat := (res_count > 0);

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ AIDS virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "AIDS" resource] }
res_count := CountResources('AIDS');
vTypes.virus_AIDS := (res_count > 0);

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ MEV# virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "MEV#" resource] }
res_count := CountResources('MEV#');
vTypes.virus_MEV := (res_count > 0);

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ INIT29 virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: find "INIT" 29 resource] }
res_handle := GetResource('INIT',29);
vTypes.virus_INIT29 := (res_handle <> NIL);
IF res_handle <> NIL THEN ReleaseResource(res_ handle);

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ ANTI virus +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: ?????????????????????????] }
vTypes.virus_ANTI := FALSE; { ??? NEED TO ADD TEST ??? }

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ MacMag vir +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ [method: ?????????????????????????] }
vTypes.virus_MacMag := FALSE; { ??? NEED TO ADD TEST ??? }

{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
{ +++++ result of the virus hunt to caller +++++ }
{ +++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
sob_virus := FALSE; { assume no viri were found }
WITH vTypes DO
BEGIN
IF virus_Scores THEN sob_virus := TRUE;
IF virus_nVir THEN sob_virus := TRUE;
IF virus_Hpat THEN sob_virus := TRUE;
IF virus_AIDS THEN sob_virus := TRUE;
IF virus_MEV THEN sob_virus := TRUE;
IF virus_INIT29 THEN sob_virus := TRUE;
IF virus_ANTI THEN sob_virus := TRUE;
IF virus_MacMag THEN sob_virus := TRUE;
IF virus_JUDE THEN sob_virus := TRUE;
END; { WITH vTypes }

Virus_Found := sob_virus;

END; { ------ Virus_Found ------ }
END.