Бронежилет для фаервола
Очень часто антивирусы и брандмауэры превращаются из охотников в жертвы. В борьбе с активной малварью еще и не такое случается. И хотя разработчики всячески пытаются защититься от посягательств со стороны зловредного кода, воздвигая целый комплекс средств противовоздушной обороны, при схватке с грамотно спроектированным зловредным кодом они обречены на поражение. Как усилить защиту уже существующих антивирусов/брандмауэров, не вмешиваясь в их машинный код и не ковыряя исходные тексты, которых у нас все равно нет? Реально ли это вообще? Еще бы!
Мужская часть населения еще помнит те давние время, когда антивирус (вместе со всеми базами и самой MS-DOS) умещался на одной «стерильной» дискетке с защитой от записи откуда его настоятельно рекомендовалось запускать. Запуск антивируса из-под зараженной операционной системы часто приводил к ложным негативным срабатываниям. То есть антивирус не находил даже известные ему вирусы, а все потому, что зловредный код слишком хорошо знал антивирус и модифицировал его код, отвечающий за распознавание заразы.
Современные антивирусы на дискету уже не влезают и вынуждены сражаться с активной малварью, в арсенале которой помимо многочисленных маскировочных методов имеется и оружие возмездия. Аналогичным образом дела обстоят и с персональными брандмауэрами. Их тяжело пробить снаружи (то есть с удаленной машины), но легко отключить локально, внедрившись в адресное пространство брандмауэра или поигравшись с элементами управления путем эмуляции клавиатурного/мышиного ввода (атаки типа WM_).
Конечно, разработчики всячески защищаются от нападок со стороны вредоносного кода (например, путем проверки целостности собственного тела). Однако получается у них не очень хорошо, и вообще создается впечатление, что они в первую очередь озабочены качеством детекции и количеством распознаваемых вирусов, то есть предпочитают нападать, а не обороняться. Вот только, вырвавшись вперед, они рискуют оказаться в плотном кольце окружения. «Независимые» обзоры также не уделяют защите никакого внимания, тестируя антивирусы/брандмауэры в лабораторных условиях.
Проактивные технологии, проверяющие все открываемые файлы на лету, действительно имеют хорошие шансы остановить распространение заразы, поскольку малварь уничтожается еще до того, как получит управление. А вот автономные сканеры, запускаемые раз в несколько дней (а то и недель), намного более уязвимы и, как показывает практика, очень плохо справляются с поиском руткитов. А если вспомнить, что зловредный код часто распространяется через дыры в безопасности (антивирусами не контролируемые), их судьба становится совсем незавидной.
Статья построена на основе анализа большого количества малвари. Мыщъх исследовал наиболее популярные техники противодействия антивирусам/брандмауэрам и разработал простые и эффективные «бронежилеты», пригодные для защиты уже существующих программ без какой бы то ни было их переделки. Поэтому не волнуйся: дизассемблер тебе не понадобится!
Стратегические ракеты межпроцессорного назначения
Как работает малварь? Какие приемы используются для ослепления защитных механизмов? Возможных способов очень много, и каждый день появляются все новые и новые. Чтобы навести в этом хаосе хотя бы какое-то подобие порядка, необходимо классифицировать основные методы, а также их производные. Тогда станет понятно, от кого и как нам обороняться.
Порядка 80% зловредных программ открывают процесс-жертву API-функцией OpenProcess, получая (в случае успешного завершения операции) дескриптор процесса, передаваемый API-функции ReadProcessMemory. Последняя читает содержимое памяти процесса-жертвы и копирует его во внутренний буфер малвари, которая путем сигнатурного поиска пытается отловить все известные ей защитные программы (список активных процессов можно получить средствами TOOLHELP32). Если подобная программа обнаруживается, малварь смотрит в свою базу сигнатур, извлекая смещение машинных команд, которые надлежит нейтрализовать, что осуществляется путем перезаписи памяти жертвы API-функцией WriteProcessMemory. В большинстве случаев достаточно заменить пару условных переходов, навсегда отучив антивирус/брандмауэр ругаться грязными словами.
В более сложных случаях малварь впрыскивает внутрь защитной программы свой код, ведущий партизанскую войну с защитным механизмом с учетом конкретных ситуаций, что намного более предпочтительно, поскольку новые версии антивирусов/брандмауэров выходят достаточно часто и создателю малвари приходится постоянно обновлять базу сигнатур. С закрытых позиций (то есть из соседнего процесса) нанести прицельный удар не так-то просто! Ошибка в один единственный байт может привести к зависанию, что не есть хорошо. Напротив, оказавшись внутри антивируса/брандмауэра, хакерский код без проблем обезвредит все «детонаторы» вполне универсальным путем: например, установит еще один перехватчик открываемых файлов поверх установленного антивирусом, а перед передачей управления последнему сотрет в проверяемом файле все следы своего присутствия (естественно, сотрет только в памяти).
Внедрение в посторонние процессы осуществляется различными путями. Классический способ (работающий только в NT-подобных системах) — создать удаленный поток вызовом API-функции CreateRemoteThread или NativeAPI-функции NtCreateThread, однако перед этим необходимо забросить зловредный код внутрь атакуемого процесса. И тут хакеру на помощь приходят API-функции: AllocateVirtualMemory (для выделения блока памяти) или QueryVirtualMemory (для поиска уже выделенного блока, пригодного для внедрения) с последующим вызовом WriteProcessMemory.
Внедрение в стиле модерн апеллирует к манипуляциям с процессорным контекстом. Новые потоки при этом не создаются. Внутрь процесса-жертвы записывается зловредный код (и тут без WriteProcessMemory никак не обойтись!), а затем API-функциями GetThreadContext/SetThreadContext регистр-указатель команд перемещается на начало зловредного кода, длина которого обычно составляет несколько десятков байт — вполне достаточно, чтобы загрузить свою динамическую библиотеку или «открыть портал». Но это уже детали реализации.
Некоторые (между прочим, достаточно многие) антивирусы/брандмауэры перехватывают вызовы WriteProcessMemory/SetThreadContext и поднимают тревогу, если запись происходит в секцию кода. Однако этот перехват достаточно легко обойти: например, вызывать API-функции не с первого байта, эмулируя выполнение пропущенных команд; или же внедряться в область данных. Правда, при активном аппаратном DEP попытка внедрения в область данных ведет к исключению, завершающему работу атакуемого приложения в аварийном режиме.
Обойти контроль за SetThreadContext можно путем подключения псевдоотладчика (созданного малварью) к процессу-жертве API-функцией DebugActiveProcess, за которой не следит ни один известный мне защитный механизм; и хакер может преспокойно получать контекст потока в свое распоряжение через генерацию отладочных событий. Такой способ внедрения в антивирусы/брандмауэры встречается все чаще и чаще.
Примерно 10% зловредных программ лезут в следующую ветку системного реестра HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs, добавляя туда свою динамическую библиотеку, которую операционная система будет проецировать на адресное пространство всех GUI-приложений, передавая ей бразды правления до их запуска. Практически все современные защитные комплексы следят за AppInit_DLLs и начинают жутко материться, если там обнаруживается новая DLL. Однако, если малварь хакнула AppInit_DLLs до запуска антивируса/брандмауэра, им остается только утереться, поскольку кто первый получает управление, тот царь и король.
Еще приблизительно 10% зловредных программ борются с защитами через оконный интерфейс. Что может быть проще! Находим окно по его заголовку (API-функции FindWindow или EnumWindows), добираемся до элементов интерфейсного управления и начинаем хачить их по своему усмотрению. Зловредный код может подавить появление нежелательных окон (например, сделав их невидимыми — API-функция ShowWindow), найти кнопку с надписью «Yes» и «надавить» на нее путем посылки соответствующих Windows-сообщений. Или же заблокировать все кнопки (API-функция WindowDisable). Наконец, можно забраться в настройки и отключить защиту, а чтобы пользователь ничего не заметил, каждый раз подсовывать ему поддельный экран. И это не фантастика! Такие вирусы уже есть, причем совсем не один, а написать их может даже школьник, едва осиливший Delphi и пролиставший по диагонали SDK.
Другой излюбленный объект атаки — файл \WINNT\System32\Drivers\etc\hosts, позволяющий сопоставлять IP-адреса с доменными именами и имеющий приоритет над DNS-сервером. То есть если малварь не хочет, чтобы антивирус обновлялся, то она просто добавляет в hosts-файл одну строчку, перенаправляя запросы к серверу обновлений куда-нибудь еще, например на локальный узел жертвы (которому соответствует адрес 127.0.0.1) или, что еще хуже, на сервер самого создателя малвари, распространяющий вредоносные обновления, которые содержат не только сигнатуры, но и машинный код. И хотя антивирусные базы в большинстве своем защищены цифровыми подписями и другими криптографическими средствами, при большом желании со стороны хакера их можно обойти.