Выживание в системах с жестоким квотированием

       

иерархия процессов, полученная утилитой tlist.exe из набора Microsoft Support Tools


Иерархия процессов видна как на ладони! Сразу ясно кто кого породил и кто откуда. А если материнский процесс уже завершился и parent PID указывает в никуда? Тогда образуется процесс "зомби", сразу же привлекающий к себе внимание, особенно если этот процесс периодически порождает новых "зомби", а сам исчезает. Увы! Это ограничение данной техники! Рождение и смерть процессов — достаточно примечательные события, чтобы долго оставаться незамеченными, впрочем, как показывает практика, они все-таки таковыми и остаются, особенно если размножается по хитрому, выдерживая перед завершением процесса небольшую паузу. Тогда в системе будут постоянно присутствовать ровно два зомби с одинаковыми именами (впрочем, путем перекрестного "опыления" можно создать два разноименных зобми, попеременно вызывающих друг друга), с постоянно изменяющимися PID'ми. Но не все пользователи обращают внимание на PID'ы. Главное, чтобы костюмчик сидел (а он сидит).

В процессе практической реализации этой схемы программист неизбежно сталкивается с проблемой передачи данных от одного процесса к другому. Как ее осуществить? Существует очень изящный трюк, позволяющий прерывать выполнение процесса в любое время (например, при антивирусной угрозе), возобновляя работу порожденного зомби с того же самого места. Это просто! Все перемененные процесса хранятся в разделяемой области памяти, туда же перед завершением записывается и регистровый контекст (чтение контекста осуществятся функцией GetThreadContext, а запись SetThreadContext, естественно контекст каждого потока должен сохраняться отдельно). Порожденный процесс считывает контекст своего предка из сохраненной области памяти, устанавливает его вручную с помощью несложной ассемблерной вставки (именно вручную!!! функция SetThreadContext корректно работает только с "замороженными" потоками, а создавать дополнительный поток только для того, чтобы восстановить контекст основного потока, нам откровенно в лом, тоже самое можно сказать и о сохранении контекста, впрочем... на вкус и цвет любителей нет).

Таким образом, с точки зрения хакера, разрабатывающего злобный вирус, нет никакой разницы сколько процессов участвует в схеме. Переключение происходит совершенно "прозрачно" и, если в довершение ко всему процесс-потомок наследует дескрипторы всех объектов своего родителя, программа выполняется как будто бы никаких переключений не происходит, вот только квоты постоянно обновляются, подкидывая свежие охапки дров в пылающий огонь!



Содержание раздела