Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #48, НОЯБРЬ 2004 г.

Немой укор за компьютерный хардкор

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

Спецвыпуск: Хакер, номер #048, стр. 048-058-1


Основы самомодификации и самообновления кода

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

Окутанный мраком тайны, окруженный невообразимым количеством мифов, загадок и легенд, самомодифицирующийся код постепенно уходит в прошлое. Рассвет эпохи самомодификации уже позади. Во времена неинтерактивных отладчиков типа debug.com и пакетных дизассемблеров типа Sourcer самомодификация действительно серьезно затрудняла анализ, однако с появлением IDA PRO и Turbo-Debugger все изменилось.

Самомодификация не препятствует трассировке, и для отладчика она полностью прозрачна. Со статическим анализом дела обстоят несколько сложнее. Дизассемблер отображает программу в том виде, в котором она была получена на момент снятия дампа или загрузки исходного файла, рассчитывая на то, что ни одна из машинных команд не претерпит изменений в ходе своего выполнения. В противном случае реконструкция алгоритма будет выполнена неверно, и хакерский корабль при спуске на воду даст колоссальную течь. Однако, если факт самомодификации будет обнаружен, скорректировать дизассемблерный листинг не составит большого труда.

Рассмотрим следующий пример:

Давай проанализируем выделенные строки. Сначала программа обнуляет регистр EAX, устанавливая флаг нуля, а затем, если он взведен (а он взведен!), переходит к метке fack_away. На самом же деле, все происходит с точностью до наоборот. Мы упустили одну деталь. Конструкция "INC BYTE PRT DS:[FACK_ME]" инвертирует команду условного перехода, и вместо метки fack_away управление получает процедура protect_proc. Блестящий защитный пример, не правда ли?

А что если расположить эту инструкцию совсем в другой ветке программы, подальше от модифицируемого кода? С другим дизассемблером такой фокус, может быть, и прокатит, но только не с IDA PRO! Взгляни на автоматически созданную ей перекрестную ссылку, ведущую непосредственно к строке "INC BYTE PTR LOC_40100F":

Самомодификация в чистом виде ничего не решает, и, если не предпринять дополнительных защитных мер, ее участь предрешена. Лучше всего поможет в борьбе с перекрестными ссылками учебник по математике за первый класс, кроме шуток! Простейшие арифметические операции с указателями ослепляют автоматический анализатор IDA PRO, и перекрестные ссылки бьют мимо цели. Обновленный вариант самомодифицирующегося кода может выглядеть так:

Что здесь происходит? Первым делом в регистр EAX загружается смещение модифицируемой команды, увеличенное на некоторую величину (условимся называть ее дельтой). Важно понять, что эти вычисления выполняются транслятором еще на стадии ассемблирования и в машинный код попадает только конечный результат. Затем из регистра EAX вычитается дельта, корректирующая "прицел" и нацеливающая EAX непосредственно на модифицируемый код. При условии что дизассемблер не содержит в себе эмулятора ЦП и не трассирует указатели (а IDA PRO не делает ни того, ни другого), он создает единственную перекрестную ссылку, которая направлена на подложную мишень, расположенную далеко от театра боевых действий и никак не связанную с самомодифицирующимся кодом. Причем, если подложная мишень будет расположена в области, лежащей за пределами [Image Base; Image Base + Image Size], перекрестная ссылка вообще не будет создана! На рисунке 4 можно видеть листинг, выданный IDA PRO.

Содержание  Вперед на стр. 048-058-2