Вирусы в UNIX, или Гибель Титаника II

       

Перехват управления путем внедрения своего кода в окрестности точки входа


Многие вирусы никак не изменяют точку входа, но внедряют по данному адресу команду перехода на свое тело, предварительно сохранив его оригинальное содержимое. Несмотря на кажущуюся элегантность этого алгоритма, он довольно капризен в работе и сложен в реализации. Начнем с того, что для сохранения оригинальной машинной инструкции, расположенной в точке входа, вирус должен определить ее длину, но без встроенного дизассемблера это сделать невозможно.

Большинство вирусов ограничивается тем, что сохраняет первые 16-байт (максимально возможная длина машинной команды на платформе Intel), а затем восстанавливает их обратно, так или иначе обходя запрет на модификацию кодового сегмента. Кто-то снабжает кодовый сегмент атрибутом Write, делая его доступным для записи (если не трогать атрибуты секций, то кодовый сегмент все равно будет можно модифицировать, но IDA PRO об этом не расскажет, т.к. с атрибутами сегментов она работать не умеет), кто-то использует функцию mprotect для изменения атрибутов страниц на лету. И тот, и другой способы слишком заметны, а инструкция перехода на тело вируса замета без очереди!

Более совершенные вирусы сканируют стартовую процедуру заражаемого файла в поисках инструкций call или jmp. А найдя таковую – подменяют вызываемый адрес на адрес своего тела. Несмотря на кажущуюся неуловимость, обнаружить такой способ перехвата управления очень легко. Первое и главное, – вирус, в отличие от легально вызываемых функций, никак не использует переданные ему в стеке аргументы. Он не имеет никаких понятий об их числе и наличии (машинный анализ количества переданных аргументов немыслим без интеграции в вирус полноценного дизассемблера, оснащенного мощным интеллектуальным анализатором). Вирус тщательно сохраняет все изменяемые регистры, опасаясь, что функции могут использовать регистровую передачу аргументов с неизвестным ему соглашением. Самое главное – при передаче управления оригинальной функции вирус должен либо удалить с верхушки стека адрес возврата (в противном случае их там окажется два), либо вызывать оригинальную функцию не командной call, но командой jmp. Для "честных" программ, написанных на языках высокого уровня и то, и другое крайне нетипично, благодаря чему вирус оказывается немедленно разоблачен.

Вирусы, перехватывающие управление в произвольной точке программы (зачастую чрезвычайно удаленной от точки входа), выявить намного труднее, поскольку приходится анализировать довольно большие, причем заранее неопределенные объемы кода. Впрочем, с удалением от точки входа стремительно возрастает риск, что данная ветка программы никогда не получит управление, поэтому все известные мне вирусы не выходят за границы первого встретившегося им RET.



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