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

Stealth patching своими руками

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

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


CALL check_something

TEST EAX,EAX

JNZ virus_or_evil_hacker_has_detected_and_will_be_destroy

CALL all_ok_continue_normal_execution

Что можно сделать? Нечестные варианты: а) подправить функцию check_something так, чтобы она всегда возвращала TRUE (XOR EAX,EAX/DEC EAX/RETN и телемаркет); б) изменить TEST EAX,EAX на XOR EAX,EAX, чтобы независимо от результатов проверки, регистр EAX всегда был равен нулю; в) удалить команду JNZ, заменив ее операцией MOV EAX,EAX (то же самое, что и NOP, только из двух байтов). Все эти способы серьезно конфликтуют с законом. На тебя могут наехать и серьезно затоптать.

А вот сравнительно честный метод взлома: дожидаемся выхода из функции check_something и тут же модифицируем регистр EAX, устанавливая его в 1 или в FFh. Это же наш регистр, выкупленный у компании Intel (или AMD), и авторское право на него не распространяется! Нет-нет, команда TEST EAX,EAX остается нетронутой, и целостность ломаемой программы никак не нарушается. Воздействию подвергается лишь сам регистр.

Как вариант, можно дождаться завершения выполнения команды TEST EAX,EAX и подправить регистр флагов, а точнее флаг Zero. Или изменить EIP таким образом, чтобы он прыгал на нужную нам ветку. Никакой закон не может заставить нас выполнять тот код, выполнять который мы не хотим! Это же сплошное насилие получается!

Правда, хороших юристов это не остановит :). Уголовный кодекс в первую очередь смотрит на конечный результат, игнорируя пути его достижения. Зарубить человека можно топором, купленным на честно заработанные, но вряд ли это станет оправданием. Другими словами, пользоваться взломанной программой все равно незаконно. Но мы же и не собираемся ей пользоваться, мы совсем другого хотим: внедриться на атакуемый компьютер так, чтобы никакая антивирусная собака даже не тявкнула.

Как это можно осуществить практически? Первое, что приходит на ум, - присоединиться к атакуемому процессу путем DebugActiveProcess (или открыть процесс с флагом DEBUG_PROCESS), некоторое время потрассировать его, дожидаясь выполнения нужной команды, затем "подрихтовать" регистры и отпустить бразды правления. Звучит прекрасно, но работает только на бумажных процессах. В диких джунглях реального двоичного кода трассировка умирает еще в упаковщике/протекторе. К тому же она очень медленно работает, что тут же демаскирует атаку, не говоря уже о том, что API-функции трассировать нельзя и приходится предусматривать обходной код, в результате чего трассировщик разрастается до размеров слона.

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

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