ssrecib@vmsa.technion.ac.il (07/06/90)
Well, here is a subroutine for checking if your EXE file has been
changed after the last run. It is based on the program posted by David
Dubois on how to store information back into the EXE file. Foe explanation
read the comments on the unit itself. After the unit listing, there
is a short program (which yoy'll have to call 'vircheck.pas') which tests
the unit. I've tried this with TP5.5 and a VERY big program, and everything
seems to work fine.
Good luck,
Igal Brener.
ssrecib@technion.bitnet
ssrecib@techunix.bitnet
------------------------------------------------------------------------
--- S T A R T O F U N I T -----
------------------------------------------------------------------------
unit VirCheck;
interface
uses dos;
{ ==================================================================
Unit: VirCheck v1.0
Author: Igal Brener
Solid State Institute and
Physics Department
Technion, Haifa
Israel
e-mail.: ssrecib@technion.bitnet
ssrecib@techunix.bitnet
July, 1990.
==================================================================
The subroutine CheckVirus is based on the program "AUTOINST.PAS" posted
to usenet news, group comp.lang.pascal by David Dubois. For details,
see his documentation. After compilation, on the first run of your
program, this subroutine will calculate the checksum of the EXE file
(passed as a parameter to the subroutine),
and store it again on disk (on the same EXE file). Next time you will
run your program, the subroutine will compare the new checksum with the
one stored, and if there is a discrepancy, you will get a notice.
The checksum calculation is done excluding the variable InstallBlock
which retains the checksum, the flag used for detecting which run
you are doing, and the last date your file was checked.
In order to make this routine work with big EXE files,
I have decided to read the EXE file from disk in records of length
RecSize, a constant you can change in the subroutine FindChecksum.
I've chosen records of ~10K, since I'm always short of heap space.
There is no check to see weather the EXE file exists, but this can
be easily added.
Any comments or problems, use my e-mail address.
Igal Brener.
==================================================================}
procedure CheckVirus(FileName:string);
type
InstallBlockType = record
already : integer;
checksum : longint;
date_Year, date_Month, date_Day: Word;
end;
Instptr= array[1..12] of byte;
const
InstallBlock : InstallBlockType
= ( already : 0;
checksum : 0;
date_Year: 0;
date_Month: 0;
date_Day: 0);
implementation
procedure CheckVirus(FileName:string);
var
c : Longint;
pInst : ^Instptr;
i : integer;
y,m,d,dow: Word;
{*****************************************************************************}
procedure ReInstall;
var
ExeFile : file;
HeaderSize: word;
begin
assign ( ExeFile, FileName );
reset ( ExeFile, 1 );
seek ( ExeFile, 8 );
blockread ( ExeFile, HeaderSize, sizeof ( HeaderSize ) );
seek ( ExeFile, 16 * ( longint ( seg ( InstallBlock ) )
- PrefixSeg
+ HeaderSize )
+ ofs ( InstallBlock )
- 256 );
blockwrite ( ExeFile, InstallBlock, sizeof ( InstallBlock ) );
close ( ExeFile );
end;
{****************************************************************************}
procedure Findchecksum ( var Checksum: Longint);
const
RecSize=10000;
type
barr = array[1..RecSize] of byte;
var
ExeFile : file;
t : word;
b : byte;
fpointer, pSize, bytesleft, i: Longint;
DirInfo: SearchRec;
p : ^barr;
begin
assign ( ExeFile, FileName );
reset ( ExeFile, 1 );
checksum := 0;
fpointer := 0;
FindFirst(Filename, Archive, DirInfo);
bytesleft := DirInfo.Size;
{ If available heap space is less than RecSize, we don't execute
this routine}
if MemAvail>RecSize then
begin
while bytesleft>0 do
begin
{Here we read RecSize bytes at a time from the EXE file}
if RecSize<bytesleft then pSize :=RecSize
else pSize := bytesleft;
GetMem ( p, pSize);
seek ( ExeFile, fpointer );
blockread ( ExeFile, p^, pSize );
i := 1;
while i <= pSize do
begin
checksum := checksum + p^[i];
inc(i);
end;
FreeMem ( p, pSize);
bytesleft := bytesleft - pSize;
fpointer := fpointer + pSize;
end;
close ( ExeFile );
end;
end;
{****************************************************************************}
begin {of CheckVirus}
GetDate(y,m,d,dow);
with InstallBlock do
begin
if already=1 then writeln('** Last date your file was verified: ',
date_Month:2, '/', date_Day:2, '/', date_Year:4);
Writeln('** Please wait, checking EXE file ... **');
findchecksum( c );
if already=1 then
begin
pInst := @InstallBlock;
i := 1;
While i<=Sizeof(InstallBlock) do
begin
c := c - pInst^[i];
inc(i);
end;
if c<>checksum then
begin
writeln('** Your EXE file has been changed: possible virus!!
Writeln(chr(7), 'Press return ');
Readln;
end;
end
else
begin
checksum := c;
already := 1;
end;
date_Year := y;
date_Month:= m;
date_Day := d;
{ update .EXE file only if checksum is ok, or if this is the first time
it is run }
if c=checksum then ReInstall;
end;
end;
end.
------------------------------------------------------------------------
--- E N D O F U N I T -----
------------------------------------------------------------------------
------------------------------------------------------------------------
--- S T A R T O F P R O G R A M -----
------------------------------------------------------------------------
program tryvirus;
uses vircheck;
begin { Main }
CheckVirus('tryvirus.exe');
{ >>> your program <<<<}
end.
------------------------------------------------------------------------
--- E N D O F P R O G R A M -----
------------------------------------------------------------------------