Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #89, МАЙ 2006 г.

Жизнь и смерть беспозвоночных в системе

Крис Касперски

Хакер, номер #089, стр. 089-050-4


Резидентные мониторы таким образом обойти уже не получится. Они перехватывают API-функции, отвечающие за чтение файлов и запуск процессов (как правильно это CreateFile и CreateProcess), прогоняя программу через анализатор _до_ ее запуска. Несколько лет назад мыщъх опубликовал в "Хакере" статью "Техника выживания в мутной воде, или как обуть антивирус", описывающую ряд элегантных и эффективных приемов, обламывающих антивирус со всеми его эвристическими анализаторами. Тогда было достаточно упаковать программу каким-нибудь навесным упаковщиком, а в точку входа вставить jump на свой thunk, использующий самомодифицирующийся код, структурные исключения или новомодные SSE команды, после чего восстанавливающий оригинальное содержимое, затертое jump'ом и передающий распаковщику бразды правления. Но виртуальные машины антивирусных систем за последнее время значительно окрепли, и часть этих трюков уже перестала работать, а скоро они перестанут работать совсем! Что же делать? Без паники, парни! Не торопитесь высаживаться на измену, а лучше повращайте хвостом и подумайте головой.

Самое простое — воткнуть в thunk функцию SetTimer/Sleep, вызывающую оригинальную точку входа через несколько секунд. Ни один из известных мыщъх'у антивирусов не анализирует аргументы SetTimer и не ждет так долго. С его точки зрения, программа выглядит так:

SetTimer(,,,);

Sleep(,);

Exit(,);

Сочетание команд, конечно, удивительное, но с точки зрения машинной логики вполне "законное". А еще можно использовать Асинхронные Вызовы Процедур (APC), создаваемые API-функцией QueueUserAPC. Да много всякого можно придумать! Но мы ведь совсем не об этом говорим! Вернемся к нашим идентификаторам родительских процессов (parent PID). Это настоящий кладезь информации для антивирусов и продвинутых пользователей. Возьмем, к примеру, утилиту tlist из комплекта Microsoft Support Tools и запустим ее с ключом "-t", а еще лучше воспользуемся NT Explorer'ом Марка Руссиновичка, бесплатную копию которого можно скачать с www.sysinternals.com/Utilities/ProcessExplorer.html Иерархия процессов видна как на ладони! А если материнский процесс уже завершился и parent PID указывает в никуда? Тогда образуется процесс "зомби", сразу же привлекающий к себе внимание, особенно если этот процесс периодически порождает новых "зомби", а сам исчезает. Увы! Это ограничение данной техники! Рождение и смерть процессов — достаточно примечательные события, чтобы долго оставаться незамеченными. Впрочем, как показывает практика, они все-таки таковыми и остаются, особенно если размножается по-хитрому, выдерживая перед завершением процесса небольшую паузу. Тогда в системе будут постоянно присутствовать ровно два зомби с одинаковыми именами, хотя путем перекрестного "опыления" можно создать двух разноименных зомби, попеременно вызывающих друг друга, с постоянно изменяющимися PID'ами. Но не все пользователи обращают внимание на PID'ы. В процессе практической реализации этой схемы программист неизбежно сталкивается с проблемой передачи данных от одного процесса к другому. Как ее осуществить? Существует очень изящный трюк, позволяющий прерывать выполнение процесса в любое время (например, при антивирусной угрозе), возобновляя работу порожденного зомби с того же самого места. Это просто! Все перемененные процесса хранятся в разделяемой области памяти, туда же перед завершением записывается и регистровый контекст. Его чтение осуществятся функцией GetThreadContext, а запись - SetThreadContext. Естественно контекст каждого потока должен сохраняться отдельно. Порожденный процесс считывает контекст своего предка из сохраненной области памяти, устанавливает его вручную с помощью несложной ассемблерной вставки. Таким образом, с точки зрения хакера, разрабатывающего злобный вирус, нет никакой разницы, сколько процессов участвует в схеме. Переключение происходит совершенно "прозрачно", и, если в довершение ко всему процесс-потомок наследует дескрипторы всех объектов своего родителя, программа выполняется, как будто бы никаких переключений не происходит. Вот только квоты постоянно обновляются, подкидывая свежие охапки дров в пылающий огонь!

Назад на стр. 089-050-3  Содержание  Вперед на стр. 089-050-5