Библиотека Интернет Индустрии I2R.ru |
|||
|
Треды и фиберы1. Дисклеймер Данный документ предназначается только для образовательных целей. Автор не несет ответственности в случае неправильного применения данного документа. Переводчик тем более. 2. Предисловие До того, как я написал данный документ, я создал два вируса, использовавших данные техники. Я думаю, что у меня есть некоторый опыт в данной области, но как бы то ни было, если вы найдете какие-нибудь ошибки или опечатки, сообщите об этом мне. Спасибо! 3. Введение Когда были выпущены Win32-платформы, все казалось абсолютно другим. VXерам пришлось учить новые техники, новые API, учиться заново как строить защиту против AV-сканеров. AVерам тоже пришлось этому учиться. Им пришлось переделать свои сканеры, эвристики и кодоэмуляторы под 32 бита. Теперь, кажется, нельзя выдумать ничего нового, чтобы обмануть AV-сканер? Действительно ли это так? Ответ: НЕТ! В этой статье я объясню новые техники. 4. Короткий взгляд на процессы, треды и фиберы 4.1 Процессы Я могу слышать ваши слова: "Гхм.... классно, но.... что ты можешь сказать о процессах, я думаю, что знаю о процессах все, что нужно. Нет, я так не думаю. Если вы не знаете о тредах, вы не знаете о процессах ничего. Итак, что такое процесс? Процесс обычно определяется как экземпляр запущенной программы. В Win32 у каждого интерфейса свое 4-х гигабайтное адресное пространство. Различие между Win32-приложениями и 16-битными программами (Win16 и DOS) заключается в том, что это адресное пространство в Win32 принадлежит только процессу (строго говоря, в случае с Win9x это не совсем так - прим. пер.). В этом адресном пространстве хранится код и данные процесса. Все требуемые DLL сохранены в адресном пространстве запущенного процесса. Процессы могут владеть различными ресурсами, например динамически резервируемой памятью, объектами ядра (файлами, семафорами, мутексами, критическими секциями...) или ветвями. Конечно, все ресурсы, занятые процессом будут автоматически освобождены, когда процесс завершит свое выполнение (еще одно различие между Win32 и Win16/DOS). Процессы инертны. Когда процесс должен начать свое выполнение, на сцене появляются треды. Последние выполняют код процесса. Кроме главного треда, у процесса могут быть и другие, поэтому у треда свой набор значений регистров и стек. У каждого процесса есть по меньшей мере один тред. В противном случае, никаких особенных причин для существования процесса нет, и он будет немедленно завершен операционной системой. Как работает переключение между тредами? Операционная система поочередно выделяет процессорное время каждому треду, за счет чего создается иллюзия одновременного выполнения всех тредов. После создания процесса, Windows автоматически создаст основной тред процесса, чтобы последний мог начать свое выполнение. Основной тред может создавать другие треды и так далее.... Windows NT умеет работать с компьютерами, на которых установлено больше одно процессора, так что треды действительно могут выполняться одновременно. Все управление тредами осуществляется ядром WinNT. Window 95/98 не умеет работать с более чем одним процессором, и хотя вы можете установить Win95/98 на мультипроцессорную систему, но задействован будет только один. Выполнение процесса можно прервать следующим образом:
4.2 Треды Я сказал, что треды выполняют код процесса. Также я сказал, что вы можете создать так много тредов, как захотите. Почему приложения используют треды? Представьте, что у вас есть какая-нибудь тупая программа, например Microsoft Word. Если вы хотите что-нибудь напечатать, Word создаст тред, который будет заниматься печатанием данных, в то время как вы сможете продолжать редактирование документа. У каждой функции треда должен быть следующий прототип:
Когда вы вызовите функцию создания треда, операционная система вызовет эту функцию:
Настоящее имя этой функции не известно, поэтому я называю ее StartOfThread. Как вы можете видеть, эта функция создает кадр SEH для треда. Если произойдет какая-либо ошибка, которую вы не станете обрабатывать, выполнение треда будет немедленно прервано (но процесс продолжит работу). Прежде, чем я расскажу, как создавать свои собственные треды, я объясню несколько вещей, которые вы должны знать. 1) Стек тредов У каждого из тредов есть свой собственный стрек в адресном пространстве процесса. Поэтому если вы используете глобальные переменные, каждый тред может получить к ней доступ. Рекомендуется, чтобы вы использовали локальные переменные. у вас будет меньше проблем при синхронизации ветвей. Стандартный размер стека равен 1MB. 2) Структура контекста У каждого треда есть свой набор значений регистров, который называется контекстом треда. Структура контекста содержит значения регистров, которые были в последний раз выполнения треда. Структура контекста единственная, состав которой зависит от процессора.
Тред можно прервать с помощью:
Как останавливать и продолжать выполнение тредов? Для этого существует две функции: SuspendThread и ResumeThread.
Первая функция увеличивает счетчик задержки, вторая уменьшает его. Тред будет выполняться только если счетчик задержки будет равен NULL. Обратите внимание. Будьте уверены, что закрываете хэндл треда с помощью функции CloseHandle. 4.3 Фиберы Продолжим? Третий сервис-пак для Microsoft Windows NT 3.51 принесла в операционную систему новые сервисы под названием фиберы. Они были добавлены в Win32, чтобы облегчить портирование приложений из UNIX в WinNT. Были написаны эти однотредные серверные юниксовые приложения, которые могли иметь "доступ ко многим клиентам за раз". Авторы этих приложений создали свои собственные библиотеки для эмуляции мультипоточности, которые могли создавать несколько стеков, сохранять регистры и позволяли переключаться между клиентским задачами. Но портирование UNIX-приложений под Win32 было настолько трудным (угадайте почему), что Microsoft решила создать несколько API-функций, чтобы облегчить этот процесс. Они не знали, что виркодерам эти функции понравятся больше, чем UNIXоидам ;-))). Какое же главное различие между тредами и фиберами? Треды реализуются с помощью ядра Windows. Ядро знает о всех секретах тредов и управляет ими согласно заданным Microsoft'ом алгоритмами. Вы можете изменить их приоритеты, вы можете приостановить или продолжить их выполнение, но тем не менее на 50% все зависит от OS: какой тред будет сейчас выполняться, какой нет и как они это будут делать. Фиберы определяются кодом пользователя. Ядро ничего не знает о фиберах, и их выполнение задается вашими алгоритмами. Так как они определяются вами, с точки зрения ядра это не является вытесняющей многозадачностью. Вы также должны знать, что тред может содержать один или более фиберов. С точки зрения ядра многозадачность применима только к тредам. Но тред может выполнять только один фибер за раз - какой именно, зависит от вас. Обратите внимание: к сожалению, фиберы не реализованы в Win95. Поэтому если вы собираетесь писать мультифиберный вирус, он будет работать только под Win98+/NT. Первое, что вы должны сделать (если вы хотите работать с фиберами) - это сконвертировать тред в фибер. Для этого есть специальная функция...
Эта функция займет память для структуры контекста фибера (около 200 байт). В контесте фибера хранится следующая информация:
Обратите внимание: структура контекста треда и структура контекста фибера - это разные вещи, помните об этом...! После инициализации контекста внутри треда создается новый фибер. Возвращаемое значение этой функци является адресом на контекст фибера. Позже нам понадобится это значение. Новый фибер можно создать с помощью следующей функции:
Сначала эта функция попытается создать новый стек размером dwStackSize байт (если данное значение будет равно NULL, то размер стека будет стандартным - 1MB). Затем она создает новый контекст фибера (куда будет сохранено заданное пользователем значение lpParameter). В lpStartAddress содержится адрес функции нового фибера со следующим прототипом:
После первого запуска фибер получит значение lpParameter - тот же, что и в CreateFiber. Вы можете делать все, что захотите в этой функции, но смотрите - у этой функции нет никаких возвращаемых параметров. Причина состоит в том, что эта функция не должна возвращаться. Если она сделает это, фибер и все фиберы, созданные в нем будут уничтожены...! Как и функция ConverThreadToFiber, функция CreateFiber возвращает адрес контекста фибера. CreateFiber не запускает фибер немедленно, потому что текущий фибер все еще запущен (в отличии от ConvertThreadToFiber). Переключение между фиберами реализуется с помощью следующего API:
У этой функции только один параметр - lpFiber - это адрес контекста фибера, которые вы ранее получили с помощью ConverThreadToFiber или CreateThread. Функция SwitchToFiber - это единственная способ переключения между фиберами. Так как вам нужно вызывать эту функцию каждый раз, когда вы хотите передать управление другому фиберу, вы полностью контролируете ваш код. Помните, управление тредами очень сильно отличается от управления фиберами, так как треды находятся под управлением ядра. Когда ваш тред получает процессорное время, только один фибер может выполняться в треде за раз. Но, как я сказал ранее, какой фибер будет выполняться, а какой нет зависит только от вас. Когда вы хотите удалить какой-нибудь фибер, используйте функцию DeleteFiber:
lpFiber - это адрес контекста фибера, который вы хотите удалить. Также будет удален стек фибера. Предупреждение: если lpFiber содержит адрес контекста текущего фибера, DeleteFiber вызовет ExitThread и текущий тред и созданные в нем фиберы будут уничтожены...! Эта функция обычно вызывает в одном фибере, чтобы удалить другой. Снова обратите внимания на различия между тредами и фиберами: треды обычно прерывают свое выполнение с помощью вызова функции ExitThread. Если вы используете функцию TerminateThread, система не удалит его стек. Тем не менее техника удаления одного фибера другим применяется очень часто. 5. Практика Вы еще помните, о чем я только что рассказал? Я надеюсь, что да, так как сейчас мы перейдем к практике. Это будет гораздо веселее, вот увидите... Сейчас вы, наверное, думаете: "hmmmm, интересно, но... как я могу использовать это в вирусах?" Не беспокойтесь, просто читайте... Как вы можете использовать фиберы? У вас, вероятно, есть какая-нибудь кульная AV-программа, которая может обнаруживать все ваши вирусы эвристическим путем. Я думаю, что вы уже сталкивались с этим. Как работает анализатор кода? Он не напрямую запускает все инструкции, но с помощью некоего эмулятора он может эмулировать все опкоды. Анализатор сравнивает регистры и другие флаги, а затем смотрит, что делает программа... Сейчас век полиморфных движков, поэтому эвристический анализ наиболее перспективен. Поэтому вопрос "Как я могу натянуть аверов" по смыслу примерно равен "как я могу натянуть эвристический анализатор и кодоэмулятор". Есть несколько путей обойти эмулятор, например трюки с PIQ, инструкции защищенного режима и fpu, техники туннелинга и так далее. Некоторые из этих техник не будут работать под Win32 или, по крайней мере, не будут иметь эффекта, который нам нужен. Поэтому здесь на сцене появляется новая техника обдуривания AV, специльно спроектированная для Win32-платформ ==> треды и фиберы. Как она работает? Просто... Представьте, как работает эмулятор процессора. У вас есть одна зараженная программа. Что "видит" эмулятор? "Хмм, в этой программе есть несколько циклов, затем она сохраняет несколько адресов (вероятно функций API), вызывает одну из них и затем я вижу бесконечный цикл. Хм, эта программа не выглядит зараженной!" Если эмулятор действительно эмулятор, он не может вызывать опкоды напрямую. Он должен эмулировать их. Хехе, к сожалению, он не может создавать треды или фиберы динамически - он не может симулировать виртуальную машину. Вы понимаете, что я хочу сказать? Ваш вирус просто создает тред/фибер и все его действия будут выполняться внутри него. Еще более лучший путь: для каждого действия ваш вирус создаст отдельный тред/фибер, поэтому у вас может быть около десяти тредов/фиберов. Самый лучший путь: комбинация тредов и фиберов. Вы действительно думаете, что эмулятор сможет это проэмулировать? Антивирусная программа сможет обнаружить ваш вирус только следующим образом:
Комбинация метаморфного движка, резидентности, сжатия, распространения (в том числе и по почте, тредов и фиберов можно будет назвать "совершенным" вирусов ;)))) Это уже не так далеко... Теперь вы знаете все, что вам нужно, чтобы написать что-то крутое. Давайте сделаем это...
Теперь у вас есть хороший каркас мультитредно-мультифиберного вируса. Вероятно, вы хотите спросить меня, является ли теперь ваш вирус "неопределяемым" простыми методами. Ответ - НЕТ. Что вам еще нужно написать?
3) Треды/фиберы, уничтожающие файлы с чексуммами AV-программ 4) Ловушки для отладчиков Обратите внимание: это всего лишь один из многих путей как использовать треды и фиберы. Можно пойти другим путем и использовать только треды вместо фиберов. Но если вы реализуете код с 15 тредами в своем вирусе, у вас будет много проблем с синхронизацией. Вы знаете, что все треды в Windoze выполняются параллельно "в одно и то же время", поэтому вам придется синхронизировать их. Есть много разных способов, как это сделать. Но это другая история. Я не хочу, чтобы это был туториал по синхронизации... Возьмите Win32 SDK, почитайте какие-нибудь хорошие книги... 6. Заключение Я надеюсь, что теперь вы знаете, что такое процессы, треды и фиберы и можете их использовать в своих вирусах (или в других, более мирных программах - прим. пер.). Треды и фиберы не сделают за вас всю вашу работу, ва придется написать еще много кода, чтобы ваш вирус был действительно крутым. Но это может помочь вам сделать ваш вирус более защищенным от антивирусных программ и узнать получше операционную систему. Benny/29A, пер. Aquila |
|
2000-2008 г. Все авторские права соблюдены. |
|