Пятница
20.09.2024
13:29


Форма входа

Приветствую Вас Новичок | RSS
Компьютерные технологии
Главная Каталог статей Регистрация Вход
Главная » Статьи » Хакинг

А ты написал свой стелс?
Стелс-технологии в вирусах
Зачем нужны стелс-технологии


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

Как же с этим бороться? Существует множество способов, причем придумывать их начали с самого момента появления антивирусов, способных искать заразу по сигнатурам. Хорошо известны такие технологии скрытия вирусного кода, как полиморфизм (в различных его формах), применение стелс-технологий. В этой статье мы рассмотрим стелс-технологии.

Что же это такое? Ну, начнем с перевода слова "стелс": by stealth - украдкой, втихомолку, тайком. Действительно, это слово в полной мере отражает суть дела, т.к. задача стелс-вируса состоит именно в том, чтобы скрыть свое присутствие в компьютере от операционной системы и всего ПО, которое использует ее функции для доступа к файлам, списку процессов и т.п.

Стелс дедушки-фронтовика

Итак, с чего все началось. Первые стелс-вирусы появились давно, когда Microsoft был маленьким, а компьютеры большими. Многие использовали тогда получающий распространение MS-DOS. В нем обживалась и зараза. Сначала простейшая, а потом все более и более совершенная. Но насколько бы ни была она совершенна, ее всегда обнаруживал антивирус. Вирусописатели перепробовали все: кодирование вирусов, изменение кода дополнением "пустых" инструкций, вроде NOP или последовательных PUSH/POP - со временем такие приемы переставали действовать.

Вот тут-то и пришло время задуматься о скрытии присутствия вирусов в ПК. Действительно, все гениальное просто: зачем изобретать хитрейшую систему мутации вируса, если можно просто сделать так, чтобы никто не знал, что этот вирус в компе есть?!

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

Что они делали? Сначала они были элементарны: перехватывали системное прерывание MS-DOS 21h и на вызовы чтения/записи файлов подставляли незараженные программы. Так антивирусы впервые оказались жестоко обмануты, однако ненадолго, до тех пор, пока не научились читать файлы посредством BIOS.

И вот началась "гонка вооружений", кто кого обманет: вирусы перехватывали BIOS, антивирусы использовали порты В/В, вирусы блокировали подобные инструкции и т.д.

Интересно, чем это кончилось? Время стелс-вирусов ушло с появлением "сверхзащищенной" ОС Microsoft Windows.

Настоящая ситуация

Ушло, но навсегда ли? Признаться, я мало слышал о вирусах под Win16. Видимо, их мало писали, то ли потому, что в Windows 3.xx было и так достаточно глюков, то ли потому, что вирьмейкеры не оправились еще от удара Microsoft. Неясно.

Но Вынь росла и ширилась, и, наконец, удвоила циферку после своего имени: Win32 получала все большее и большее распространение. Вирусописатели один за другим пересели на ASM под Win32.

Проблемы оказались в чем-то схожими с MS-DOS'овскими: надо было скрыть вирус. Правда, решение их оказалось намного сложнее: во-первых, из-за того, что Win32-приложения работают исключительно в среде защищенного режима процессора, во-вторых, в Win гораздо больше функций для работы с объектами (файлами, процессами), да и объектов стало поболее, а, значит, и больше следов, которые может оставить вирусный код.

Но гений вирьмейкеров и тут их не подвел. Бессонные ночи кодинга сделали свое дело: слово "стелс" возродилось из пепла. Что же должен скрывать "идеальный" современный стелс-вирус (будем считать, что он резидентный и распространяется, помимо прямого заражения файлов, еще и по e-mail)? Давай по порядку.

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

Все это можно сделать, перехватив системные вызовы API на каком-либо уровне - либо на уровне пользователя, либо на уровне ядра.

Процесс, покажи личико

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

...
RegisterServiceProcess(NULL, 1);
....

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

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

Для начала нам необходимо зарегистрировать фрагмент памяти, в котором будет лежать код (для этого можно воспользоваться функциями OpenFileMapping и MapViewOfFile из kernel32.dll). Туда-то мы и поместим код треда, который будет выполняться в процессе-жертве. Теперь необходимо заставить жертву запустить этот тред. Как же выполнить какой-то код в чужом адресном пространстве? Есть, пожалуй, два пути: один - это использование CreateRemoteThread, а второй - это замена адреса какой-то импортированной из системной библиотеки функции (например, GetDC из gdi32.dll) на адрес своей функции, предварительно записанной в процесс. У первого пути при всех его положительных моментах (например, предельной простоте) один минус - он работает лишь на NT, но ты ведь хочешь универсальности, правда? Поэтому рассмотрим второй.

Не будем заострять внимание на поиске и открытии хендла самого процесса, а перейдем сразу к делу: запишем в программу код запуска треда вируса. После этого нам надо найти таблицу импортируемых функций программы и переписать адрес одной из импортированных функций так, чтобы он указывал на наш код запуска. И то, и другое можно сделать при помощи функций ReadProcessMemory и WriteProcessMemory. Естественно, стоит переписывать какую-то часто используемую функцию, например, GetMessage. Но не забудь, что после запуска своего кода необходимо вернуть все на свои места, а то жертва перестанет корректно функционировать.

Третий способ чуть легче, он особенно удобен, если ты пишешь свое детище на C. Состоит он в том, чтобы воспользоваться библиотекой Detours от разработчиков Microsoft ;). Она позволяет загрузить в чужой процесс свою DLL-библиотеку, а уж та может творить внутри все, что угодно. Сравните весь тот бред, что был написан про второй способ, с лаконичным куском кода:

// hProcess - хендл процесса
// szDllPath - путь к подгружаемой библиотеке
DetourContinueProcessWithDllA(hProcess, szDllPath);

Он загрузит в жертву нашу DLL'ку, в функции ProcessAttach которой ты пропишешь все, что собираешься сделать. Просто, как раз-два-три. Неприятно одно: с собой приходится таскать целую библиотеку подгружаемых багов aka DLL :), что, согласись, в вире - излишне.

Четвертый способ я опишу лишь концептуально, без деталей, а то я уж больно сильно увлекся кодингом :). Этот способ состоит в подмене функции, которая выдает приложениям список процессов. Точнее не функции, а ряда функций: Process32First и Process32Next. Тут же напрашивается идея использования для этого той же техники, что и в предыдущих двух способах.

Но в идеале каждой пользовательской программе нужно подсовывать "исправленные" версии таких функций. Как же это сделать? Делается это, как оказалось, несложно и достаточно лаконично. Дело в том, что их код хранится в одном месте физической памяти, а в каждый процесс лишь отображается (спасибо дескрипторным таблицам, о которых написано в статье про Ring0), таким образом, остается лишь изменить эти функции в физической памяти, и счастье придет само собой! =) Но обычным способом это сделать невозможно, потому что эта область защищена от записи. Тупик? Нет! Решение все-таки существует.

Оно состоит в переходе на более глубокий уровень Windows, на уровень ядра или в так называемое нулевое кольцо защиты (Ring0). Находясь именно в этом уровне, мы можем делать то, что обычным программкам на Visual Basic'е и не снилось, мы можем изменять физическую память, в том числе и наши функции. Как попасть в нулевое кольцо защиты? Для этого существует специальный механизм эскалации привилегий в процессорах фирмы Intel.

Этот способ, хотя и достаточно прост в описании, на практике оказывается самым сложным, потому как программирование на уровне ядра - это хождение по лезвию бритвы, чуть что не так, и наблюдаешь за красивым синим экраном :). Но зато это и единственный по-настоящему надежный путь. В самом деле, какому антивирусу захочется копаться в пучинах кернела?

А коннект-то - вот он!

Итак, мы скрыли процесс, но это еще далеко не все. Как только твой питомец попытается подключиться к какому-нибудь хосту в интернете, юзер, наученный статьей про защиту от заразы ;-), воспользуется утилитой netstat, увидит подозрительные коннекты со своего компа и тут же переставит Винду. Обидно, правда? Особенно, если ты пару недель парился и писал модуль для ковыряния в кернеле.

Хорошо, боремся с netstat'ом:

Ну, во-первых, можно "исправить баги" или попросту удалить сам netstat. Удалять - это совсем по-ламерски, поэтому будем отстреливать баги, а именно: нужно заставить netstat не говорить о тех коннектах, которые у нас есть. Сделать это можно, например, так: переименовываем netstat.exe во что-нибудь еще, вместо него записываем свой бинарник, который запускает оригинальный netstat и фильтрует его вывод. Дешево и сердито. Это можно сделать, например, таким образом:

hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0);
SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr);
DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS);
CloseHandle(hChildStdoutRd);


После этого создаем порожденный процесс (тот самый настоящий netstat) и читаем то, что он нам выдает при помощи:

ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL);

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

Вот что из этого получилось у меня (внимательно следи за портом 3707). Вывод оригинального netstat'a:

...И вывод исправленного:

Правда, так лучше, если учесть, что троян висит именно на порту 3707? :)
Как альтернативу этому способу можно предложить скрыть сетевые подключения при помощи замены функции в ядре (об этом я уже писал выше). А заменить нужно лишь одну функцию - GetTcpTable - именно она возвращает список TCP-подключений.

А если не от кого скрывать?..

Я неоднократно упоминал всякие ring 0, уровни ядра и прочую подобную ерунду. У тебя, наверное, возникла идея: а почему бы не сделать вирь, который бы просто находился в резидентном состоянии в ring 0, то есть с теми же правами, что и ядро. Это практически идеально позволило бы защититься от большинства антивирусов.
Должен тебя разочаровать, ты не первый, кто придумал нечто подобное. Такую идею, например, реализовывал Win.CIH (aka Чернобыль). Кстати, именно поэтому он обладал возможностью стирания BIOS'а. Правда, на момент написания его был известен способ перехода в Ring 0 лишь в Win9x, сейчас дела обстоят хуже: этот режим стал доступен и в WinNT, так что жди нового, улучшенного WinNT.CIH'a... Представляю, как в твоем мозгу копошатся темные мысли о создании страшного недетектируемого ring0-вируса. Не обольщайся, многие современные антивирусы работают в том же кольце защиты, поэтому и там тебе придется укрываться от их зоркого взгляда :-(.

Будущее маленьких стелсов

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

Кто знает, может быть, ты будешь автором такого виря? ;-)

Что же ждет нас завтра?..


Время стелс-вирусов ушло с появлением "сверхзащищенной" ОС Microsoft Windows. Ушло, но навсегда ли? Помимо скрытия из списка процессов, мы получим еще одно приятное свойство...
by stealth - украдкой, втихомолку, тайком
Способ номер два состоит во внедрении в тело чужого процесса в памяти прямо "на лету". Теоретически это очень просто...
Хочешь посмотреть программу, модифицирующую ядро, в действии? Внимательно следи за процессом apihook.exe ;).
Внедряемся в ядро и исправляем FindXXXProcess...
...И возвращаем все на свои места!
сверху: hook_off.bmp
ниже: taskman_off.bmp
Слабо повторить? ;-)
Категория: Хакинг | Добавил: qtex-program (01.05.2009) | Автор: qtex
Просмотров: 1973 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Меню сайта

Категории раздела
Мои статьи [15]
Хакинг [19]
Хакеры и программисты
BIOS [13]
Железо [9]
Системное администрирование [15]

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Поиск

  • Друзья сайта

    Copyright MyCorp © 2024