Техника снятия дампа с защищенных приложений

>>> Врезка подлянки


Нормальные упаковщики (UPX, PKLITE, PECOMPACT) сжимают исполняемый файл без потерь и после завершения распаковки он возвращается к своему первоначальному виду, что делает процесс снятия дампа тривиальной задачей. Протекторы, в стремлении усилить защиту, зачастую идут на довольно рискованный шаг— они "слегка" корежат обрабатываемый файл с таким расчетом, чтобы он мог работать только под протектором, а после освобождения от него, становится нежизнеспособным. В народе трюки такого типа называют "подлянками" и это неспроста! Любое вмешательство в упаковываемый файл — это потенциальный источник сбоев и критических ошибок, отравляющих жизнь не только хакерам, но и законопослушным пользователям. Избавляться от "подлянок" нужно любой ценой, поэтому, нам не помешает познакомится с ними поближе.

 

кража байт с OEP: самая простая и широко распространенная подлянка, используемая даже в таких безобидных протекторах как, например, ASProtect. Суть ее заключается в том, что упаковщик "крадет" несколько инструкций из оригинальной точки входа, сохраняет их в потайном месте (возможно, в замаскированном или зашифрованном виде), а после завершения распаковки эмулирует выполнение краденных байт. Чаще всего для этой цели используется стек (и тогда краденные байты обычно становятся операндами инструкций PUSH), реже — прямое воздействие на регистры и память (при этом краденные инструкции трансформируются в псевдокод и в явном виде нигде не сохраняются). Суть в том, что в точке входа распакованного образа оригинальных байт уже не оказывается и снятый дамп становится неработоспособным. К нашему счастью, подавляющее большинство программ начинается со стартового кода, который является частью библиотеки времени исполнения (RTL), поставляемой вместе с компиляторами. Используя оставшийся "хвост" стартового кода мы легко отождествим компилятор и восстановим краденные байты из его библиотеки. Если же данного компилятора в нашем распоряжении не окажется, первые несколько байт стартового кода в 9 из 10 случаев вполне предсказуемы и зачастую их удается восстановить самостоятельно (естественно, для этого необходимо иметь опыт работы с различными RTL).
Кстати говоря, IDA  Pro распознает компилятор именно по первым байтам стартового кода и если они отсутствуют или искажены, механизм FLIRT работать не будет, а это значит, что мы останемся без имен библиотечных функций и процесс дизассемблирования займет намного больше времени.

 

полиморфный мусор в OEP: вместо того, чтобы красть байты с OEP, некоторые протекторы предпочитают модифицировать стартовый код, разбавляя значимые инструкции бессмысленным полиморфным мусором. Это никак не влияет на работоспособность снятого дампа, но ослепляет "FLIRT", вынуждая нас либо вычищать полиморфный мусор, либо определять версию компилятора "на глазок", загружая сигнатуры в ручную (IDA Pro это позволяет).

переходники в таблице импорта к куче: протектор Themida использует довольно пакостный прием, серьезно затрудняющий восстановление таблицы импорта. Непосредственные адреса API-функций заменяются переходниками на область памяти, выделенную VirtualAlloc (т. е. кучу), которая по умолчанию в дамп не попадает, поэтому восстанавливать импорт приходится вручную. Это несложно, но утомительно — ищем вызовы API-функций, ведущие к куче (то, что это именно куча, а не что-то другое, можно определить по карте), дампим соответствующий регион памяти на диск, удаляем переходники, заменяя их действительными адресами, после чего запускаем Import Reconstructor или другую утилиту аналогичного назначения и... нет, это еще не все! Это только начало! Помимо создания переходников некоторые функции копируются протектором целиком! Подробнее об этом приеме можно прочитать в статье "точки останова на win32 API и противодействие им" — раздел "копирование API – функций целиком", которая лежит на http://kpnc.opennet.ru/adt.zip.

замена jx с последующей эмуляцией: при "отвязке" программ от протектора Armadillo самое сложное это восстановление оригинального кода программы. Защита дизассемблирует обрабатываемый файл, находит в нем условные и безусловные переходы, записывает поверх них команду INT 03h, а сам переход сохраняет в своей внутренней таблице переходов.


Процесс- сервер перехватывает исключение, возбуждаемое инструкцией INT 03, смотрит откуда оно пришло, извлекает из таблицы соответствующий этому адресу переход и эмулирует его выполнение с помощью арифметических манипуляций с регистром флагов (то есть, в явном виде переходы нигде не хранятся!). Вот три главных минуса такого решения: во-первых, нет никакой гарантии, что защита правильно дизассемблирует обрабатываемую программу и не спутает переход с другой командой; во-вторых, эмуляция требует времени, существенно снижая производительность и, наконец, в-третьих, от взлома это все равно не спасает! Дизассемблировав эмулятор переходов (а дизассемблировать его несложно) и обнаружив таблицу переходов, хакер в считанные минуты напишет скрипт для IDA Pro или OllyDbg, удаляющий все INT 03 и восстанавливающий оригинальные переходы. Существует даже полуавтоматический взломщик Armadillo, написанный двумя богами распаковки — infern0 и dragon (http://www.wasm.ru/baixado.php?mode=tool&id=220), в следующих версиях которого обещана полная автоматическая распаковка и дезактивация Armadillo.

преобразование в байт-код: протекторы Themida и Start-Force позволяют преобразовывать часть машинного кода защищаемой программы в язык виртуальной машины, то есть в байт-код (так же называемый p-кодом). Если виртуальная машина глубоко "вживлена" внутрь протектора, то отломать защиту, не "умертвив" при этом приложение, становится практически невозможно, как невозможно непосредственно дизассемблировать байт-код. По меньшей мере для этого необходимо разобраться с алгоритмом работы виртуальной машины и написать специальный процессорный модуль для IDA Pro или свой собственный дизассемблер. Это очень трудоемкое занятие, отнимающее у хакера кучу сил и времени, а ведь байт-код виртуальной машины в следующих версиях протектора может быть изменен и ранее написанный процессорный модуль/дизассемблер окажется непригодным. Это наиболее стойкая защита из всех, существующих на сегодняшний день, однако, не стоит забывать о двух вещах: во-первых, если протектор становится популярным, а его новые версии выходят редко, создание процессорных модулей становится экономически оправданным и защиту начинают ломать все желающие, если же новые версии выходят чуть ли не ежедневно, то навряд ли у разработчика протектора будет достаточно времени для радикальной перестройки виртуальной машины и ему приходится ограничиваться мелкими изменениями байт-кода, которые выливаются в мелкие изменения процессорного модуля и протектор продолжат ломать.Во-вторых, хакер может "отодрать" виртуальную машину от протектора, совершенно не вникая в тонкости интерпретации байт-кода, лишний раз подтверждая известный тезис: сломать можно все… со временем.


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