Содержание статьи
В любой современной системе бесконечно много точек, в которых может проявляться присутствие трояна. Хаотичный анализ всех этих точек не только неэффективен с точки зрения трудозатрат, но и в корне неверен.
Фундаментальная задача при ручном поиске троянов — свести бесконечное многообразие троянских признаков к минимальному количеству векторов поиска, грамотная проработка которых гарантирует достижение цели. Для этого надо понять суть троянской программы, ее системообразующий принцип. Зная принцип, разработать надежный алгоритм поиска зловредов в произвольной системе, даже ранее неизвестной, — дело техники. Это то, чему мы учим на своих семинарах для сисадминов-киберниндзя.
Итак, вначале общий принцип, затем универсальная методика и наконец — особенности Мака.
Но сперва — disclaimer:
- Мы ищем только ядро атаки — троян, который живет в системе и совершает в ней какие-то действия. Мы не ищем одноразовые трояны (это бессмысленно), компоненты доставки трояна, такие как drive-by-скрипты, эксплойты, дропперы (это задача для отдельного исследования) и засвеченные на той или иной конференции концептуальные техники (большинство из них неприменимы в реальности).
- Если обследуемая система представляет ценность как мишень для промышленного или политического шпионажа, то материалов этой статьи заведомо недостаточно, так как целевые трояны проектируются с учетом известных методик форензики.
Принцип
У любого трояна есть несколько фундаментальных «жизненных потребностей». Это первичные классовые признаки, которые характерны абсолютно для всех троянов, независимо их от функционала и платформы. Вот они:
- Троян где-то хранит свой код.
- Троян откуда-то получает управление в процессе загрузке системы.
- Троян реализует свое предназначение (нагрузка и контакт с хозяином).
- Троян может скрывать все вышеперечисленное. А может не скрывать.
Идея в том, чтобы сфокусироваться только на поиске этих первичных признаков, и только тех из них, которые действительно необходимы.
На самом деле достаточно поиска по одному пункту (2). Любой троян откуда-то стартует, поэтому грамотный анализ этого вектора — для краткости назовем его «автозагрузки» — может дать такой же результат, как и если бы мы последовали всему плану, но с меньшими усилиями. А руткиты мы просто обойдем стороной: руткит может скрыть что-либо только в работающей системе, а мы анализируем систему в статике.
Итак, поскольку поверхность анализа нормирована до предела, алгоритм поисков должен быть исчерпывающим «by design», чтобы ничего не упустить.
Алгоритм
0. Подготовка
Перед ручным анализом должны быть быстро исчерпаны тривиальные и автоматизированные методы поиска вредоносного кода (антивирусы, антируткиты, визуальный просмотр списка процессов и прочие). Ценность антивирусов невелика, но было бы глупо потратить час собственных интеллектуальных ресурсов на поиск известного трояна, который антивирус найдет за десять секунд.
1. Автозагрузки
Составляем перечень всех известных точек старта кода для целевой системы. Не забываем, что в процессе загрузки системы могут исполняться не только приложения пользователя, но и модули ядра, задания планировщика, скрипты, код предзагрузки системы (MBR, UEFI) и так далее.
Основные источники информации — первичная документация для разработчиков, «библии» для системных администраторов, исследовательские материалы. Важно на этом этапе:
- чем полнее перечень автозагрузок, тем больше вероятность найти троян, даже самый продвинутый;
- чем лучше приоритизирован перечень по статистической вероятности обнаружения трояна, тем меньше времени займет поиск.
2. Анализ
Отключаем систему, монтируем жесткий диск к заведомо чистой системе (либо загружаемся с внешнего диска) и методично анализируем пункты составленного перечня на предмет подозрительных элементов.
Если элемент перечня не является файлом (например, ключ реестра в системах семейства Windows) — используем утилиту для статического парсинга соответствующего хранилища (в данном случае reglookup, regmount и множество им подобных).
Анализ автозагрузок в работающей системе также возможен, но может дать ложные результаты, так как мы умышленно пренебрегли выявлением руткит-перехватов для экономии времени.
Особый случай — вирусный механизм загрузки, когда код стартует не из известной точки автозагрузки, а из легитимного модуля. На сегодняшний день паразитный метод запуска кода достаточно редок, а его известные агенты (TDL, ZeroAccess) должны быть уже найдены на этапе «0» с помощью антивирусных утилит. Для критичных систем (см. disclaimer, пункт 2) имеет смысл хранить заведомо чистый слепок системы, относительно которого можно обнаруживать модификации в исполнимых файлах.
3. Итог
Сейчас у нас уже должен быть файл трояна. Если файл не найден, а подозревать наличие в системе нетривиального целевого трояна нет оснований, то причина может быть только одна: недостаточно тщательная проверка. Что-то упущено на одном из предшествующих этапов. Если файл трояна найден, осталось его изучить. Системный анализ вредоносного кода — отдельная тема, которую мы рассмотрим как-нибудь в другой раз.
Особенности OS X
Троянская индустрия для Мака пока развита слабо. Для троянов нет необходимости изобретать концептуальные техники, так как успешно работают простые и документированные. Поэтому поиск трояна на Маке не должен составить труда или занять много времени.
Для статического анализа файловой системы OS X загружаемся в Single User Mode (<Command + S> при загрузке системы) и монтируем корневой раздел (mount -wu /
). Как вариант, можно загрузить систему с заведомо чистого загрузочного диска и работать с GUI. Если системный раздел зашифрован (legacy FileVault, FileVault2), обращаемся к соответствующим инструментам для его дешифровки (см., например, VileFault и libfvde).
Пользователи в OS X ограничены в привилегиях по умолчанию. Поэтому наиболее велика вероятность того, что троян установился в один из пунктов автозагрузки, доступных для обычного пользователя. С этих пунктов и начинаем анализ:
- /Library/LaunchAgents/ — приблизительный эквивалент ключа реестра HKCU\…Run в Windows;
- /Library/Preferences/ — настройки меню, виджетов и многое другое + ссылки на соответствующие исполнимые модули;
- /var/at/tabs/, /usr/lib/cron/tabs/ и тому подобное — файлы планировщика.
При анализе автозагрузок нас интересуют все ссылки на файлы, указанные в стандартных для OS X (plist) или UNIX-нативных (например, crontab) конфигурационных файлах. На троянский исполнимый модуль может ссылаться как его собственный файл настроек plist, так и модифицированный plist легитимного приложения (хотя вторая техника не встречалась мне in the wild). Чтобы не усложнять анализ, мы просто получаем ссылки на файлы из всех подряд директорий автозагрузки в порядке приоритета и оцениваем их на предмет подозрительности.
Пример — мои автозагрузки:
MacBook-Air-Alisa:~ user$ plutil -convert xml1 Library/LaunchAgents/*.plist -o - | grep "<string>/"
<string>/System/Library/Frameworks/AddressBook.framework/Resources/AddressBookSourceSyncScheduleHelper</string>
<string>/Applications/VirtualBox.app/Contents/MacOS/vboxwebsrv</string>
# Выдача предыдущей команды отфильтрована по сигнификатору абсолютного пути "/",
# поэтому надо проверить, что модуль трояна не прописался в текущую директорию:
MacBook-Air-Alisa:~ user$ ls Library/LaunchAgents/ | grep -v ".plist$"
Анализируем ссылки на файлы примерно так:
- Устанавливала ли я это приложение? Если нет:
- Что знают в интернете о модуле с таким именем? Если ничего или ничего хорошего:
- Что я могу узнать об этом модуле за пять минут? (strings , ps aux | grep и тому подобное)
Подозрительные к этому моменту файлы складываем в отдельную папку и позднее анализируем более детально или отправляем на анализ любимому производителю антивирусов.
Если предположить, что трояну удалось повысить привилегии, список и его анализ усложняются. Ниже перечислены некоторые наиболее вероятные глобальные автозагрузки.
- Точки старта системных демонов, приложений, заданий планировщика для всех пользователей:
- /Library/StartupItems
- /Library/LaunchAgents
- /Library/LaunchDaemons
- /System/Library/LaunchAgents
- /System/Library/LaunchDaemons
- /Library/Preferences/
- /etc/crontab
- Модули ядра, загружаемые kextd при старте системы:
- /System/Library/Extensions
- Устаревшие директории:
- /etc/rc.local
- /etc/mach_init.d/
- /etc/mach_init_per_login_session.d/
- /etc/mach_init_per_user.d/
Отмечу, что известные на сегодняшний день трояны для Мака используют всего несколько пунктов из этого списка.
Пример: получаю перечень загружаемых при старте системы модулей ядра не от Apple (никаких kextstat, мы же работаем в статике!) и немного исследую модуль, вызвавший подозрение:
MacBook-Air-Alisa:~ user$ cat `find /System/Library/Extensions/ -name Info.plist` | grep "CFBundleIdentifier" -A 1 | grep -v com.apple | grep -P ".*\..*\." | awk 'a !~ $1; {a=$1}'
…skip…
<string>com.hp.hpio.hp_psa640_io_enabler</string>
<string>com.hp.hpio.hp_psa530_630_io_enabler</string>
<string>com.jmicron.JMicronATA</string>
<string>com.promise.driver.stex</string>
<string>com.silabs.driver.CP210xVCPDriver</string>
<string>com.silabs.driver.CP210xVCPDriver64</string>
<string>com.softraid.driver.SoftRAID</string>
<string>com.MosChip.driver.MCS7840</string>
MacBook-Air-Alisa:~ user$ ls /System/Library/Extensions/ | grep promise
MacBook-Air-Alisa:~ user$ mdfind -onlyin /System/Library/Extensions/ "promise"
/System/Library/Extensions/PromiseSTEX.kext
MacBook-Air-Alisa: Chrome> google "com.promise.driver.stex"
About 45 results (0.23 seconds)
…skip…
MacBook-Air-Alisa:~ user$ cat /System/Library/Extensions/PromiseSTEX.kext/Contents/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>11A511</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>PromiseSTEX</string>
<key>CFBundleGetInfoString</key>
<string>Version: 5.0.62, Copyright (c) 2010 Promise Technologies, Inc.</string>
…skip…
MacBook-Air-Alisa: Chrome> google "Promise Technologies, Inc."
Promise Technologies, Inc. | ATA RAID controllers and subsystems ...
www.motionmedia.com › Hardware
…skip…
Напоследок немного исследовательского вдохновения. Все знают, что система OS X основана на FreeBSD и Mach и наследует некоторые их особенности. Менее известно, что эти особенности унаследованы бессистемно, наряду с устаревшими функциями проприетарной части системы. Например, стандартный для UNIX загрузочный скрипт rc.local отсутствует по умолчанию на моем Маке. А вот цитата из Mac Developer Library про него: «You can put these two commands in your /etc/rc.local file to execute at startup time». Читай: точки старта кода, унаследованные из старых версий OS X и ее предшественников, с большой вероятностью могут поддерживаться в последних версиях OS X, даже если отсутствуют в стандартной инсталляции. Тему нестандартных автозагрузок на Маке предоставим исследовать читателю. Рекомендуемая литература: Mac Developer Library Technical Note TN2083, раздел Deprecated Daemonomicon.