Анимация
JavaScript
|
Главная Библионтека Пример 3.13. = raov out al, OADh 64h, al Наконец, можно использовать вызовы INT 1 и INT 3, но не там, где их обычно ищу7 а, например, в прерывании от таймера, и с активацией ветки не сразу, а после некоторое временной задержки. Очевидно, этот способ конфликтует с перестановкой векторов ил,-замещением обработчиков, и применять их можно только поочередно. Комбинируя описанные методы, можно построить достаточно надежную систему защиты. 3.1.5. Борьба с отладчиками защищенного режима Некоторые отладчики защищенного режима ловятся на противоотладочные трюки, предназначенные для борьбы с отладчиками реального режима. Так, Soft-Ice попадается на приемы, связанные с потерей одного трассировочного прерывания после префиксной команды CS: (КОП 2Eh). cs: pushf pop ax pushf pop bx sub ax, bx add BeingDebugged, ax Другие приемы против отладчиков защищенного режима основаны на предоставл мых ими API. Так, DeGlucker, предоставляя API по 1NT 15h (функции OFFxx), намертво зависает на конструкции: mov ах, OFFOlh int 15h Третья фуппа приемов борьбы с отладчиками защищенного режима заключается в искажении состояния аппаратных отладочных средств. Так, если известно, что для трассировки программы применяется регистр DR1, то можно исказить либо его значение, либо значение управляющих битов в регистре DR7. Однако уже есть отладчики (DeGlucker 0.05), которые сами используют отладочные регистры, а отлаживаемой программе использовать их не дают, эмулируя обращение к ним. И наконец, четвертая группа приемов против отладчиков защищенного режима основана на использовании ощибок конкретных отладчиков. Так, Soft-ICE (по крайней мере некоторые версии) некорректно обрабатывает команды обращения к регистру DR7, что позволяет ловить его на таком, например, фрагменте кода: mov еах, dr7 or еах, 2000h test dr7, eax eax, dr7 eax, 2000h DebuggerNotFound Ветка нормальной работы Дальше идут команды реакции на отладчик или, допустим, взведения флага такой реакции. 3.1.6. "Изощренное" программирование Приемы защиты программ от отладчиков и дизассемблеров для программирования задач ответственного целевого назначения, конечно, хороши. Но, как уже отмечалось, абсолютно надежных защит не бывает, и поскольку задача разработчика защиты - вынудить противника потратить на взлом время, достаточное для принятия контрмер, только противоотладочными трюками офаничиваться не нужно. Нелишне также затруднить исследование профаммы и после того, как противник обойдет или устранит все ловушки ]дя хакерского инструментария. Для этого необходимо сделать профамму высокочитабельной для нас, но малопонят-40Й в дизассемблированном виде, а под отладчиком - создающей впечатление хаотичного набора условных и безусловных переходов. Эта задача решается применением так называемого "изощренного" программирования. Можно выделить несколько основных направлений: экзотическая, имеющая необычный вид реализация алгоритмов с использованием редких команд процессора или их нестандартных сочетаний; реализация нескольких полностью эквивалентных вариантов одного и того же алгоритма, при каждом обращении к которому случайным образом выбирается один из вариантов его реализации; засорение кода "мусором" - командами, не влияющими на обработку наших данных (кроме некоторого увеличения времени обработки на "засоренных" участках). Рассмотрим эти приемы подробнее. Экзотическая реализация алгоритмов. Допустим, у нас есть некоторый флаг (или переменная), для которого критически важна проверка на 0. Однако мы не желаем явно писать команду СМР АХ, О и вообще по возможности хотим обойтись без команд переучи управления. Первое, что приходит в голову - использовать команды, пригодные для неявной про-Рки на 0. Например, использовать команды двоично-десятичной арифметики. Пример 3.14. = mov daa pushf pop and jz ax, OurFlag ax ; Неявная проверка флага нуля ах, 40h FlaglsZero Разумеется, в реальной программе получение флагов и проверка наличия флага нуля должны быть разнесены для все того же затруднения исследования. Однако этот вариант, хотя и применимый, относительно прост для взлома. Взлом значительно усложняется, если мы установим обработчик нулевого значения флага на ШТ О (деление на 0), а проверку реализуем как деление чего-нибудь на значение флага, загруженное в любой допустимый регистр. В этом случае никакого перехода на обработчик нулевого значения флага нет вообще, а кроме того, некоторые отладчики аварийно завершают программу при выполнении деления на 0. Заметим, что так можно реализовать и проверку ненулевых значений, вычитая их из значения нашей переменной и деля что-нибудь на результат. При этом, очевидно, значение нужно принудительно пересылать в любой допустимый регистр, а обработчик INT О должен представлять собой реализацию некоторого хеш-преобразования, возвращающегс индекс массива адресов точек входа в обработчики конкретных значений (или сам адрес). Реализация эквивалентных ветвей. Для затруднения исследования программы пол отладчиком польза от этого приема очевидна. В самом деле, если мы, находясь в отладчике, попадаем то на одну команду, то на несколько, это явно не упростит понимание алгоритма программы. Приведем простой пример. Операция NEG (преобразование числа в дополнительный код) эквивалентна исключающему ИЛИ со "всеми единицами" и инкременту результата Напишем макрос, реализующий алгоритм с двумя возможными ветвями его выполнения. ; ====== Пример 3.15. ================================= ; ====== NEG над 16-разрядньм регистром. ============== XNEG16 MACRO Reg local XNEG2, XNEGQ push ax ; Используется процедурой Random call Random ; Некоторая подпрограмма XNEG2: XNEGQ: ja pop neg imps ENDM al, 30 XNEG2 ax Reg XNEGQ Reg, OFFFFh Reg ; генерации случайных или ; псевдослучайных чисел Это лишь простейший пример, относительно легко поддающийся анализу. Для затруд-ения анализа возможно: g увеличить число ветвей (реализуется не для всех алгоритмов); g реализовать ветви в виде обработчиков прерываний (INT 1, INT 3, ГЫТ 4, INT бит. д.) и обращаться к ним не напрямую, а путем создания соответствующих ситуаций (взведением флага TF, засылкой команды INT 3 на место заранее поставленного NOP, делением на О и пр.), что, кстати, еще и расширит противоотладочную подсистему; g увеличить число проверок случайного числа. . ====== Пример 3.16. =================== ; ====== NEG над 16-разрядным регистром. XNEG16 MACRO Reg LOCAL XNEGl, XNEG2, XNEGQ push ax ; Используется процедурой Random call Randoml ; Некоторая подпрограмма ; генерации случайных или ; псевдослучайных чисел cmp al, 30 ja XNEG2 XNEGl: XNEG2: XNEGQ: pop neg imps push call ENDM XNEGQ ax ax Random2 ; Другой генератор ah, 73 XNEGl Reg, OFFFFh Reg Вообще говоря, в "изощренном программировании" нет готовых рецептов. Здесь все зависит от разработчика конкретной защиты, от его фантазии и знания используемого процессора. Засорение кода. Под засорением кода будем понимать искусственное внесение в него команд, не имеющих отношения к реализуемому алгоритму, которое либо затрудняет его анализ, либо делает этот анализ более канительным, более утомительным и, следовательно, Тебующим больше сил и времени. Речь идет о манипуляции незадействованными регистрами; установке/сбросе hckoxq рых флагов, выполнении нескольких команд, на эти флаги не влияющих, с последующ условным переходом, который на самом деле заведомо выполнится или заведомо не вы. полнится; обработке нескольких одинаковых структур, из которых только одна содер данные нащего алгоритма и т. д. Все это не только увеличивает объем дизассемблиро, ванного текста, но и отвлекает внимание от защищаемого алгоритма. Полезно засорять код еще и макросами или вызовами, эмулирующими ввод с клавиатуры команд Soft-Ice, TR или комбинаций клавищ распространенных отладчи. ков, или даже просто нажатие некоторых случайных клавищ. Очевидно, при этом нужно почистить буфер перед вызовом любой подпрофаммы обращения к клавиатуре. 3.2. Антивирус из вируса 3.2.1. Классификация вирусов и других вредных программ Параметры классификации. Вредные профаммы можно классифицировать: Ш по степени опасности; по заражаемым объектам; по методу заражения; т по методу скрытия своего наличия в системе; т по исходному языку профаммирования. Возможно расщирение списка параметров классификации. Классификация по степени опасности. Вредные профаммы по степени опасности можно разделить на: т безобидные, т. е. не содержащие в себе никаких деструктивных функций и проявляющиеся только размножением; безопасные, т. е. проявляющиеся сообщениями, видеоэффектами и пр.; опасные, т. е. способные вызвать серьезные сбои в работе вычислительной системы, "засадить" пользователя в систему меню, выхода из которой нет или он сильно затруднен и т. д.; очень опасные, т. е. способные уничтожить информацию в файлах, системных областях, на логических дисках, вызвать физическое повреждение железа, а также дропперы опасных по данной классификации профамм, имеющих некоторое время замедления. Классификация по заражаемым объектам. По объектам, используемым для пространения, вредные профаммы можно разделить на: g файловые вирусы, т. е. профаммы, которые тем или иным способом присоединяются к файлам; g загрузочные вирусы, т. е. профаммы, записывающие свой код в системные области дисков; g сетевые вирусы, или "черви", т. е. профаммы, которые тем или иным способом пересылают свои копии по вычислительным сетям; g "троянские кони", т. е. профаммы, которые замаскированы под какие-либо безвредные профаммы; могут также дописываться к файлам, системным областям или сетевым сообщениям по алгоритмам соответствующих вирусов, но для этого требуется специальная профамма "приваживания"; сами троянцы возможности саморазмножения не имеют; щ "логические бомбы", т.е. запрофаммированные разработчиком нормальной по идее профаммы троянские компоненты, срабатывающие лищь по определенному условию (например, при отсутствии ключевой информации на 0-й дорожке винчестера). Классификация по методу заражения. Различные вредные профаммы различным образом классифицируются по методу заражения объекта-жертвы. Файловые вирусы по этому параметру делятся на: I вирусы-спутники, которые тем или иным образом переименовывают файл-жертву (обычно меняют расщирение) и записывают себя в файл с прежним именем жертвы; замещающие вирусы, которые записывают себя поверх файла-жертвы, не сохраняя его старого содержимого (очевидно, все замещающие вирусы относятся к очень опасным); пристыковывающиеся вирусы, или паразитические вирусы, которые дописывают себя к профамме таким образом, что сначала получает управление код вируса, а затем он вызывает код жертвы (методы пристыковки и передачи управления коду жертвы зависят от форматов исполнимых файлов в конкретной ОС и здесь не рассматриваются, равно как и системно-независимый алгоритм, реализуемый чаще всего в HLLP вирусах); Зафузочные вирусы по этому параметру бывают: сохраняющие код загрузчика в какой-то редко используемый сектор (например, на 0-й дорожке) и передающие на него управление; замещающие код зафузчика и берущие все его функции на себя (по определению все такие вирусы относятся к опасным, так как антивирус вынужден записывать в системную область хранимый внутри стандартный зафузчик). Троянцы по этому параметру бывают: " автономные, т. е. замаскированные под полезную профамму тем или иным способом; пристыковочные, т. е. дописываемые с помощью профаммы-дроппера к нормальным выполнимым файлам; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [ 38 ] 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |