[comp.lang.pascal] Program selftesting and viruses

ts@uwasa.fi (Timo Salmi LASK) (07/28/90)

(*
     Programmers: Help fighting viruses and patching.

Viruses and unauthorized patching are problems which should be
fought against by the PC community. This program demonstrates a
simple and a reasonably general, fast selftest to detect whether the
program has caught a virus, or if it has been amateurishly patched.
The code is easily incorporated in any Turbo Pascal source code. The
idea is to check whether the file date and size have been altered.
Most .exe viruses work by appending their code to the .exe file
altering the file size. Trivial patching changes the file date.
Either of these is detected by selftest.
...................................................................
Prof. Timo Salmi        (Moderating at anon. ftp site 128.214.12.3)
School of Business Studies, University of Vaasa, SF-65101, Finland
Internet: ts@chyde.uwasa.fi Funet: gado::salmi Bitnet: salmi@finfun
*)

program SelftestDemo;

uses Dos;

(* Define a datatype for the required information *)
type SelftestRecordType = record
                             size  : longint;
                             year  : word;
                             month : word;
                             day   : word;
                             ok    : boolean;
                           end;

(* Define a selftest constant. Give initial values to match your
   own program *)
const SelftestRecord
        : selftestRecordType
        = (size  : 3184;
           year  : 1990;
           month : 7;
           day   : 27;
           ok    : true);

(* Tests whether file size and / or filedate have been changed.
   Writes a warning message *)
procedure SELFTEST (var selftestRecord : selftestRecordType);
var FileInfo : SearchRec;
    FileDate : DateTime;
    oksize   : boolean;
    okdate   : boolean;
begin
  oksize := true;
  okdate := true;
  FindFirst (ParamStr(0), AnyFile, FileInfo);
  if DosError <> 0 then selftestRecord.ok := false;
  if selftestRecord.ok then
    if (FileInfo.Attr and VolumeId = 0) and
       (FileInfo.Attr and Directory = 0) then
      begin
        if FileInfo.Size <> selftestRecord.size then
          oksize := false;
        UnpackTime (FileInfo.Time, FileDate);
        if FileDate.year  <> selftestRecord.year then
          okdate := false;
        if FileDate.month <> selftestRecord.month then
          okdate := false;
        if FileDate.day   <> selftestRecord.day then
          okdate := false;
        selftestRecord.ok := oksize and okdate;
      end;
  if not selftestRecord.ok then
    begin
      writeln (#7, 'Warning for a patched or detached program, or a potential virus');
      if not oksize then
        writeln (ParamStr(0), ' filesize has been altered');
      if not okdate then
        writeln (ParamStr(0), ' filedate has been altered');
    end;
end;  (* selftest *)

procedure LOGO;
begin
  writeln;
  writeln ('SELFTEST demo by Prof. Timo Salmi, 27-Jul-90');
  writeln ('University of Vaasa, Finland, ts@chyde.uwasa.fi');
  writeln;
end;  (* logo *)

(* Main program *)
begin
  LOGO;
  SELFTEST (selftestRecord);
  if not selftestRecord.ok then halt;
  writeln ('Hello world and whatever');
end.  (* selftestDemo *)

frisk@rhi.hi.is (Fridrik Skulason) (07/30/90)

This program works in most cases - however, it is not effective against some
of the latest viruses, which fool it by making the program appear unchanged,
after the virus is in control.

-frisk

-- 
Fridrik Skulason      University of Iceland  |       
Technical Editor of the Virus Bulletin (UK)  |  Reserved for future expansion
E-Mail: frisk@rhi.hi.is    Fax: 354-1-28801  |   

ts@uwasa.fi (Timo Salmi LASK) (07/31/90)

In article <1875@krafla.rhi.hi.is> frisk@rhi.hi.is (Fridrik Skulason) writes:
>This program works in most cases - however, it is not effective against some
>of the latest viruses, which fool it by making the program appear unchanged,
>after the virus is in control.

This is cartainly true, and the purpose of the code is to easily
weed out elementary cases, which are the most frequent anyway.  One
of the points was to make the code simple to understand and include. 
The other alternative is to imbed a checksum in the .exe file.  But
the code is much more complicated, because the checksum (either
direct or crc) constant itself within the program must be skipped
when recalculating the checksum.  Another problem is that the
checksum must be calculated fast.  Else it renders the host program
useless.  I have the code also for calculating and checking the
direct checksum of an .exe file in addition to size & date check. 
This should be fairly effective.  This will be included in the
upcoming update of my Turbo Pascal units tspas21.arc. 

...................................................................
Prof. Timo Salmi        (Moderating at anon. ftp site 128.214.12.3)
School of Business Studies, University of Vaasa, SF-65101, Finland
Internet: ts@chyde.uwasa.fi Funet: gado::salmi Bitnet: salmi@finfun