Реферат Курсовая Конспект
Приемы против отладчиков реального режима - раздел Компьютеры, NAG SCREEN Чтобы Понять, Как Противодействовать Отладчикам Реального Режима, Необходимо...
|
Чтобы понять, как противодействовать отладчикам реального режима, необходимо изучить сам процесс отладки. 8086 процессор предоставлял для этого одну команду, один флаг и две исключительные ситуации. Не слишком густо, но прожить можно.
Легче всего понять концепцию контрольных точек останова исполнения программы. Для этого используется однобайтовый код ОхСС. Когда процессор встречает его, он вызывает исключительную ситуацию (в просторечии "дергает прерыванием") int 0х3. При этом в стеке запоминается регистр флагов, указатель текущего кодового сегмента (регистр CS), указатель команд (регистр IP), запрещаются прерывания (очищается флаг FI) и сбрасывается флаг трассировки.
Что из этого следует? Отлаживаемая программа полностью, включая все аппаратные прерывания, "замораживается" и поступает в монопольное распоряжение процессора, а значит и отладчика. Последнему доступен весь код программы и операционной системы(!) для чтения, анализа и даже модификации. Отладчик может также изменять значение регистров и указателя команд. При этом доступ к последнему осуществляется через стек. Содержимое стека при входе в int 0х3 будет следующим:
IPß-------------SP
CS
Регистр флагов
Обычно отладчики сразу сохраняют все регистры, а потом обращаются к ним через стек или присваивают их локальным переменным. Эта информация вам пригодится, если возникнет необходимость написать собственный отладчик или его подобие.
Какими недостатками обладает предложенный метод? Самое неприятное в нем то, что точка останова непосредственно модифицирует код (при этом вынуждая отладчик сохранить измененный байт, чтобы потом была возможность вернуть его обратно). Поэтому для отлаживаемой программы не составит труда обнаружить этот факт и удалить точку останова. Для этого можно воспользоваться корректирующими кодами Рида-Соломона, которые позволяют определить местоположение контрольного байта или использовать контрольную сумму кода для расшифровки какого-нибудь фрагмента. Рассмотрим следующий пример crackl2.asm:
Repeat:
PUSH SI
XOR AХ,АХ
LEA SI, Start
Get_CRC;
LODSB
ADD AH,AL
CMP SL,offset Crypted
JB Get_CRC
POP SI
LODSB
XOR AL,AH
STOSB
CMP SI .offset _end
JB Repeat
Crypted:
Похоже на обычный расшифровщик, за исключением того, что ключ генерируется на основе контрольной суммы исполняемого кода. Этим убиваются два зайца: невозможна никакая модификация кода и, главное, контрольные точки останова исказят результат. Воспользуемся, например, TurboDebuger-oM или даже Solt-ice.
Пошаговая трассировка программы никак не блокируется защитой, но очень утомительна. Попробуем установить точку останова. Но где? Ясно, что в строке Crypted ни в коем случае нельзя. Рассмотрим, что при этом произойдет:Обратите внимание на значение регистра AL — оно равно ОхСС. Контрольная точка исказила код, и теперь он уже не может быь корректно расшифрован. Однако установка контрольной точки в пределах расшифровщика исказит вычисляемую контрольную сумму его тела.
Это наглядно демонстрирует следующий дамп:
cs:0119 сmр si,0151
cs:011D jb 0105
cs:011F pop si
cs;0120 shl word ptr [bр+si-01],1
cs:0123 fst dword ptr[di]
cs:0125 stc
cs:0126 sbb bx,[bp+di-6676]
cs:012A wait
cs: 012B xchg bx, ax
cs:012C clc
cs:012D call EADO
Как мало этот мусор похож на работоспособный код! Разумеется, дальше трассировку продолжать бессмысленно. Так мы ни к чему не придем. Попробуем воспользоваться эмуляционным отладчиком, например сир386. Виртуальные контрольные точки никак не изменяют существующего кода, а поэтому не вносят никаких искажений ц его работу.
Но представляет интерес решить эту проблему менее мощными средствами. Самое простое — положить кирпич на клавишу F7 и идти пить чай, а тем временем программа будет расшифровываться.
Если же говорить серьезно, то необходимо дождаться расшифровки хотя бы первой инструкции. При этом допустима только пошаговая (F7). а не Step Over (F8) трассировка (последняя также устанавливает ОхСС в конце команды). Теперь можно безболезненно установить точку останова, так как код уже расшифрован и не модифицируется.
Этому, однако, можно воспрепятствовать, применив многопроходную расшифровку кода. Это, конечно, сложнее программируется, но затраченные усилия с лихвой окупятся, так как под обычным отладчиком это уже не будет исполняться. Кроме того. шифровка затрудняет дизассемблирование. Обычные дизассемблеры вообще не смогут обработать код и выдадут что-то наподобие следующего листинга:
crackl2.1st Sourcer v5.10 9-Mar-99 1:53 pm page I
43C7:01lF 6C Dl 62 FF D9 15 db 6Ch,ODIh, 62h,OFFh,OD9h, 15h
43C7:0125 F9 1В 9В 8A 99 ЭВ db OF9h, IBh, 9Bh, 8Ah, 99h, 9Bh
43C7:012B 93 F8 ЕВ АО E9 E9 db 93h,OF8h,OE8h,OAOh,OE9h,OE9h
43C7:0131 F6 F8 db OF6h,OF8h
43C7;0133 57 38 76 7В 3В 7В db 'W8v(8xttx'
Впрочем, это не относится к IDA, который умеет обрабатывать скрипты. Например, следующий скрипт расшифрует весь необходимый код, позволяя дизассемблировать файл:
auto a,sym,ch;
sym=0 ;
for (а=0;а<Оx1Г;а++)
sym=sym+Byte (MK_FP (0х1000, OxlOO+a} ) ;
sym = sym s OnFF;
Message ("CRC= %x n", sym),
for (a-OxllF;a<Oxl51;a++)
{
ch = Byte(MK_Fp(OxlOOO,a));
ch = ch " sym;
PatchByte (HK_FP (0х1000, a) ,ch) ;
}
Аналогичным образом можно снять любую мыслимую шифровку. Подробнее об этом уже рассказывалось, и я не буду повторяться. Разве что для разнообразия приведу скрипт для HIEW, как для более распространенной утилиты. Для начала нам необходимо узнать контрольную сумму расшифровщика. Подсчитывать ее можно, например, в регистре BL, для чего достаточно одной команды
ADD BL,AL
HIEW, к сожалению, не поддерживает полностью автономных скриптов, поэтому необходимо вручную "провести" его от 0х0 до 1х1Е. Посмотрим теперь, какое значение имеет регистр BL. Если все сделано правильно, то там находится число ОхВ8. Попробуем расшифровать им остальной код:
XOR AL, ОхВВ
В результате получится следующее:
0000001F: В409 mov ah, 009
00000021: BA2701 mov dx,00127
00000024: CD21 int 021
00000026: C3 retn
00000020: 09 ВЙ 27 01-CD 21 C3 ^3-52 41 43 4B-20 30 78 31 Ц' =!^CRACK 0х1
00000030; 31 2E 20 8F-EO АЕ й3 EO-AO RC АС АО-20 A2 ЕВ AF 1. Программа вып 00000040: АЕ АВ AD A5-AD АО 20 ЕЗ-Е1 AF A5 E8-AD AE OD OA олнена успешно 00000050: 24--- $
Таким образом, приемы против отладчиков "прозрачны" для дизассемблеров. Конечно, дизассемблеры не эквивалентны отладчикам и даже частично не покрывают возможности последних. Поэтому желательно все же найти способ заставить отладчик работать.
Напоминаю, что мы пока говорим о 8086 микропроцессоре и никаких аппаратных точек останова еще нет. Эмуляция может быть теоретически осуществима, но практически для нее не хватит ресурсов процессора. Можно, однако, поступить проще: перед каждой командой обращения к памяти контролировать достоверность результата и при необходимости исправлять его. Это очень ресурсоем-кая операция, к тому же возможная только в режиме пошаговой трассировки (что само по себе сильно замедляло выполнение программы на первых процессорах): поэтому большинство отладчиков полагало, что среднему пользователю эти возможности не понадобятся, и не реализовывало их.
Казалось бы, сегодня, в век быстрых процессоров, мы должны были бы давно забыть об этом и устанавливать контрольные точки, где нам вздумается, не беспокоясь, что это может нарушить правильное выполнение программы. Однако ничего не изменилось за прошедший десяток лет. Вот грустный пример программы под Win32. Почему грустный? Да потому, что штатным отладчиком с ним ничего нельзя будет сделать. Рассмотрим его подробнее:
Int main (int Argc, Char*, argv[])
Char c[]=”Hello World! n”;
_asm(
LEA ESI,From
LEA EDI,To
xor eax,eax
From:
MOV al,CS:[ESI]
INC ESI
ADD ah,al
cmp esi,edi
jb From:
LEA ESI,c
MOV EDI,ESI
Repeat:
LODSB
OR AL,AL
JZ To
XOR AL,AH
STOSB
jhp Repeat
To:
}
printf(c);
return 0;
}
He правда ли, этот пример почти полностью повторяет пример под MS-DOS десятилетней давности? Изменилась только одна команда — в Windows не так-то просто модифицировать исполняемый код, вместо этого программа расшифровывает данные-
Попробуйте установить контрольную точку в границах ассемблерного фрагмента. Используется, к примеру, отладчик для MS VC 6.0 или даже Soft-Ice! И в том, и в другом случае строка 'Hello Word!' будет расшифрована некорректно и вместо ожидаемого приветствия на экране появится бессмысленный мусор. Любопытный факт! На протяжении всей истории существования платформы Intel отладчики повторяют одну и ту же ошибку, которую с успехом используют разработчики защит.
А теперь подумаем, что будет, если мы подсчитаем контрольную сумму всей программы, а не только одного расшифровщика, Правильно! Ни одной точки останова нельзя будет установить! Отладка обычными средствами станет невозможной! Впрочем, Soft-Ice позволяет установить аппаратные точки останова командой Ьрт (в отличие от Ьрх), и легко выйти из положения.
А вот отладчики от Borland и MicroSoft будут наталкиваться на непреодолимую преграду лени своих разработчиков. Впрочем, не будем строги к последним. Они рассчитывали все же нс на хакеров, а на прикладных разработчиков, в жизни которых подобной ситуации, может быть, никогда и не встретится.
Вообще, первоначально никто и не помышлял об агрессивных средствах контроля исполнения программ. Отладчик представлял собой мирное и уязвимое существо, уживающееся с исследуемым кодом в одном адресном пространстве и разделяющим общие ресурсы. Речь шла исключительно об отладке своих собственных программ, более того — специально рассчитанных на взаимодействие с отладчиком.
Давайте посмотрим, как может защита использовать тот факт, что отладчик использует общие с ней ресурсы. Как уже отмечалось выше, программная точка останова генерирует исключительную ситуацию (прерывание) номер 3. При этом процессор читает адрес обработчика из таблицы векторов. Он находится по смещению ОхС в нулевом сегменте.
Защита может прочитать этот адрес и записать в обработчик немного (или много — кому как понравится) "мусора", убивая при этом отладчик. Разумеется, для этого необходимо выяснить, что это именно отладчик, а не что-то другое. По умолчанию Int 0х3 обрабатывается MS-DOS и обработчик состоит из одной команды IRET (OxCF). Если обнаруживается нечто иное, то с некоторой степенью вероятности это и будет отладчиком. Чтобы нейтрализовать последний, достаточно переустановить int 0х3 (и int 0х1 — но об этом ниже) на свой обработчик, в котором нужно вывести сообщение с просьбой нс отлаживать эту программу.
Впрочем, это может и не сработать. "Умные" отладчики могут отслеживать чтение программой таблицы векторов прерываний и "подсовывать" предыдущие значения обработчиков. Сегодня это умеет делать большинство из них, в том числе и Soft-Ice. Отметим также, что в Windows прикладной программе никто попросту не даст манипулировать векторами и это становится уже неактуально.
Отлаживаемая программа может также содержать опкод ОхСС, беспорядочно и в изобилии разбросанный по всему ее телу и при этом делающий что-то полезное. Например, обработчик int 0х3 может расшифровывать код или вызывать int 0х21. В результате произойдет конфликт ресурсов: отладчику и защите понадобится прерывание int 0х3 — каждому для своих нужд. Обычный отладчик при этом будет постоянно "всплывать" на каждом ОхСС, и если последнее установить в глубоко вложенном цикле, то отладка превратится в пытку. Однако у некоторых отладчиков можно отключить всплытие по точке останова. К таким отладчикам относится, например, trsutil Евгения Касперского.
Заметим, что это не в меньшей степени актуально и для платформы Windows. Наглядным примером может служить CRACK13, который при попытке запуска под отладчиком (скажем, интегрированным с MS VC) вызывает останов последнего, командой int 0х3. Забавно, но его разработчики не предусмотрели возможности отключения этого действия.
Словом, Windows по-прежнему остается хорошим полигоном для борьбы защит с отладчиками. Это блестяще подтверждается на старом как мир способе срыва стека. Казалось бы, современная операционная система должна следить за поведением приложений и не допускать подобных глупостей с их стороны, однако все остается таким же как и десять лет назад.
Рассмотрим еще раз поведение процессора при встрече инструкции ОхСС — контрольной точки останова: он заносит в стек флаги и значение указателя команд и вызывает обработчик. Давайте представим, что при исполнении некоторого критического фрагмента кода защита присвоила указателю стека нулевое значение. А стек, как известно, растет вверх, т.е. от старших адресов к младшим. Когда процессор, встретив int 0х3, попытается сохранить (занести) в стек регистр флагов, он не сможет этого сделать, так как стек уже исчерпан. Операционной системе ничего не останется сделать, как завершить некорректно работающее приложение, потому что восстановить его работоспособность уже будет невозможно.
Этот прием продемонстрирован в программе CRACK13. Однако в приведенном примере можно просто удалить команды xchg esp.eax, чтобы приложение успешно работало под отладчиком. Хорошая защита должна этому препятствовать. Здесь возможны множество путей. Например, можно подсчитывать контрольную сумму своего кода, а потом полученным значением расшифровывать некоторый фрагмент. Впрочем, хакеру будет нетрудно расшифровать код вручную и удалить защищенный расшифровщик. Поэтому рекомендуется прибегать к динамической шифровке или читать данные командой pop. Действительно, рассмотрим следующую ситуацию:
H|E|L|L|O| |W|O|R|L|D|…..
^
|
|
esp-----popà
Если установить esp на начало строки, а потом последовательно извлекать из стека байт за байтом, то получим некий аналог LODSB, только более мощный, так как он может читать в любой регистр и оставляет esi нетронутым под нужды программы. При этом любое вмешательство отладчика в процесс приведет к затиранию читаемых данных и краху программы. Неплохо, очень неплохо, — в этом можно убедиться на примере CRACK13. Попробуйте запустить его под отладчиком! Но лучше не пробуйте, ибо ничего хорошего все равно не получится.
Немного поразмыслив, мы придем к выводу, что в данном случае POP AX можно безболезненно заменить на LODSW. Но нетрудно так спроектировать код, чтобы подобная замена была невозможна. Например, достаточно задействовать все свободные регистры, а также команду PUSH, ближайшим аналогом которой будет DEC EDISTOSW — несколько большая по длине и к тому же тесно связанная с флагом направления (который защита может умышленно изменить на противоположный) и с регистром АХ.
Что предпринять хакеру в такой ситуации? Пожалуй, воспользоваться дизассемблером или эмулирующим отладчиком. Однако последних под Windows, похоже, еще не существует, поэтому остается только первое.
Впрочем, посмотрите, во что обходится разработчику подобная вольность. Профилировщик VTue (кстати, очень хороший профилировщик) наглядно демонстрирует, что выделенный фрагмент отнимает большую часть процессорного времени. Если не прибегнуть к оптими.чапии и всякого рода ухищрениям, то можно потерять скорость, а вместе с ней и клиентов.
Но какое отношение имеет профилировщик ко взлому? И может ли он быть хоть чем-то полезен хакеру? Может, еще как! Особенно если это хороший профилировщик. Заметим, что защитный механизм написан целиком на ассемблере. С виду написан довольно аккуратно, но на деле коряво и неоптимально. Это позволяет с легкостью находить в исполняемом файле ассемблерные фрагменты. Возможно, что один из них — искомый защитный механизм.
Особенно это актуально на платформе Windows, где большинство грамотных защит пишутся на ассемблере, а не на языках высокого уровня. Оборотной стороной такого подхода становится открытость защитного кода. Как уже было показано выше, локализовать защитный механизм — это наполовину взломать его.
Практически все антиотладочные механизмы основаны на оригинальных приемах программирования и не поддерживаются языками высокого уровня. Это вынуждает разработчика прибегнуть к ассемблеру. Пии этом многие (в том числе и старые) программисты забывают, что архитектура процессоров не стояла на месте и за последние несколько лет представления об оптимизации кардинально изменились. Код, оптимальный для 80486, не будет автоматически оптимальным для Pentium's. Необходимо позаботиться хотя бы о спаривании команд, без чего ассемблерная "заплатка" будет сильно выделяться на фоне оптимизированного компилятором кода.
Вторым отладочным механизмом 8086 процессора является поддержка трассировки исполнения программы. Трассировка — это пошаговое выполнение инструкций. Во времена 8086 она была единственным средством отладки программ на процессорах того поколения. Организовывалась она с помощью "ловушки". Под ее нужды выделялся один из флагов (TF — trace flag). Если он был установлен, то после выполнения каждой инструкции процессор генерировал исключение 1 (т.е. вызывал int 0х1). При этом он сохранял в стеке регистры флагов и указателя команд и при входе в обработчик автоматически очищал флаг трассировки, чтобы не привести систему к краху.
При этом отладчик никак не был защищен от агрессивных действий отлаживаемой программы. Описанные выше приемы применимы и к этому случаю. Так, чтобы войти в обработчик, int 0х1 требуется по крайней мере шесть байт стекового пространства. При этом стековыми регистрами свободно владеет отлаживаемая программа и нет никакой возможности зарезервировать эти шесть байт для отладчика. Как это может использовать защита, было показано выше.
Несовершенство механизма трассировки позволяло отлаживаемой программе не только обнаружить отладчик, но и выйти из-под его контроля. Действительно, регистр флагов мог читаться и модифицироваться отлаживаемой программой. Проверить, установлен ли флаг трассировки, защите ничего не стоило. После чего был резонный повод для отказа в работе. Однако хакер мог нейтрализовать такие проверки. Кроме того, отладчик может анализировать следующую инструкцию и если она воздействует на флаг трассировки, то эмулировать ее выполнение. Поэтому разработчики защит начали использовать весьма изощренные приемы, один из которых показан ниже (CRACK14):
PUSHF
MOV AX,2577h
MOV BP,SP
LEA DX,NewlntOx77
INC Byte ptr [BP+I]
INT 21h
POPF
INT 77h
Newlnt0x77:
NOP
MOV AL, [BP+I]
SHL Al, 7
ADD SP,6
LEA SI,Crypted
MOV CX, offset _end - offset Crypted
Repeat:
XOR Byte ptr [SI],AL
INC SI
LOOP Repeat
Crypted:
MOV АН, 9
LEA DX, About
INT 21h
RET
About DB 'Hello, Sailor!', ODh,OAh,'$'
Если этот фрагмент запустить под отладчиком, то расшифрованный код будет выглядеть следующим образом:
2298:0126j 34 В9 ХОR AL,89
2298:0139j ЗА АЕ 81 4D СМР CH,Byte ptr [BP]+4D81
2296:012Cj Al 43 C8 MOV AX,Word ptr [C843]
2298:012Fj E5EC IN AX, [EC)
2298:0131j EC IN AL,DX
229S:0132j EF OUT DX,AX
2298:0133j I AC LODSB
2298:0134j D3 El SHL CX,CL
2298;0136j E9 EC EF JMP F125
2298;0139j F2 REPNE
Полученный мусор может привести систему к краху, но едва ли будет нормально выполняться. При этом защитный механизм настолько "размазан" по коду, что обнаружить его можно только при тщательном "ручном" анализе. Маловероятно, что найдется гений, который напишет отладчик, автоматически восстанавливающий алгоритм работы защитного механизма.
Вся загвоздка именно в "рассеянии" инструкций защиты среди не относящихся к ней команд. Рассмотрим подробнее следующий фрагмент:
PUSHF
MOV AX,2577h
MOV ВР,SР
LEA DX,NewlntOx77
INC Byte ptr [BP+I]
INT 21h
POPF
Выделим следующую последовательность инструкций:
POSHF
MOV BP,SP
INС Byte ptr [BP+I]
POPF
Нетрудно видеть, что она устанавливает флаг трассировки. Однако это неочевидно для отладчика, особенно если учесть, что эти четыре команды могут быть разбросаны по сотне-другой килобайт кода. Требуется чертовски нетривиальный алгоритм, который мог бы отследить значения всех регистров в произвольной точке. К тому же флаг трассировки можно установить десятками способов. Например, при выходе из прерывания, используя сохраненный в стеке регистр флагов.
Кроме того, ни в коем случае не надо делать тривиальную проверку типа
TEST [ВР+11,1
JHZ under_debuger
Это слишком заметно и к тому же элементарно нейтрализуется удалением условного перехода. Используйте значение флага трассировки, например, для расшифровки или в арифметических выражениях. Последнее особо трудно обнаружить и исправить. Для этого как минимум потребуется полностью проанализировать алгоритм работы приложения.
Как с этим жить хакеру? Ответ все тот же: используйте дизассемблеры и эмулирующие отладчики. И все усилия разработчиков защиты пойдут прахом. Сегодня можно с уверенностью сказать, что все антиотладочные приемы стали неактуальны. И просто непостижимо то упорство, с которыми некоторые разработчики тратят свое время и силы на борьбу с отладчиками реального режима, которые уже давно никто не использует.
Кроме того, нормальная операционная система просто не позволит прикладной программе манипулировать с флагом трассировки. Совсем недавно это было не так. Защита могла не только читать, но и сбрасывать флаг трассировки, тем самым выходя из-под контроля отладчика. Заслуживает уважения, что разработчики без всякой поддержки со стороны процессора все же научились защищаться от агрессивных приложений. Однако все же редкие отладчики позволяют программе трассировать саму себя. А защиты это могут активно использовать. Например, для расшифровщика или интерпретатора. К последнему мы еще вернемся, а пока рассмотрим следующую программу (crackl6):
Repeat:
LODSW
MOV [SI-2] ,BX
LOOP Repeat
He правда ли, малопонятный цикл? На самом деле это часть расшифровщика. А другая его часть хитро спрятана в обработчике Int 0х1:
NewIntOlh:
XOR AX,9FADh
MOV BX,AX
IRET
T.e. на самом деле расшифровщик полностью выглядит так:
Repeat:
XOR AX,9FRDh
MOV BX,AX
LODSW
XOR AX,9FADh
MOV BX,AX
MOV {SI-2],BX
XOR AX,9FADh
MOV BX,AX
LOOP Repeat
Когда-то это был популярный прием, использовавшийся многими защитами. Еще не существовало достаточно мощных отладчиков, и самотрассирующиеся программы представляли для хакеров увлекательную головоломку. Сегодня это уже перестало быть актуальным. Конечно, вполне возможно написать самотрассирующуюся программу под Windows, но это потребует определенного труда и квалификации разработчика. Это не то чтобы действительно сложно, но попросту бесполезно. В арсенале хакера наверняка найдутся средства, способные этому противостоять.
Очень жаль, что разработчики защит порой не учитывают возможности современных отладчиков и, смутно представляя себе архитектуру последних, пытаются создать защиты, которые совершенно "прозрачны" для большинства из них. И это несмотря на то, что даже современные отладчики имеют много дыр, которые до сих пор не залатаны именно в силу того, что не были массово найдены и использованы разработками защит.
Рассмотрим некоторые из них. Неочевидно с первого взгляда, но практически все отладчики перехватывают часть исключений с целью предотвращения некорректной работы программ. Это в первую очередь int 0х6 (неверный опкод) и int 0х0 (деление на нуль или переполнение). Ничего не стоит построить защиту, активно использующую эти ресурсы. Например, для расширения существующих команд микропроцессора. При этом не будет существовать никакого способа заставить эту защиту работать под отладчиком, который самостоятельно перехватывает эту исключительную ситуацию и блокирует работу.
Однако не стоит принимать вышеизложенное как руководство к написанию защит подобного типа. Напротив, я всячески призываю этого не делать. Ведь не только отладчик перехватывает исключение "неверный опкод", но и менеджеры расширенной памяти (ernm386, qemm), операционная система Windows, да мало ли еще кто. В любом случае вашему клиенту не понравится, если программу придется запускать в "голой" MS-DOS или отказываться от использования Windows и драйверов расширенной памяти.
Гораздо больше подходит на эту роль переполнение при делении. Эта исключительная ситуация признана довольно рядовой, и любая операционная система позволяет приложениям обрабатывать ее самостоятельно. В самом деле, иначе было бы невозможно существование математических программ. Как бы вам понравилось, если бы при попытке деления на ноль в электронной таблице Windows, сообщив о некорректном поведении приложения, закрывала бы его? Вообще непонятно, почему отладчики "взъелись" на это исключение и принялись обрабатывать его независимо от приложений. Самое интересное, что этим грешат даже некоторые эмулирующие отладчики!
Самое сложное в использовании этого приема — найти такой алгоритм, который не позволял бы обойти его непосредственным вызовом int 0. Т.е. если в теле защиты есть некая инструкция DIV, которая вызывает обработчик исключения, то ничего не стоит заменить ее на непосредственный вызов прерывания int хх, предварительно переустановив обработчик на любое свободное значение.
Рассмотрим следующий пример, где подобная замена просто невозможна (взят из реальной защиты):
NewintOOh:
ADD SI,AX
CBW
ADD SP,6
Repeat:
LODSW
DIV AН
STOSB
LOOP Repeat
Зашифрованный фрагмент содержал помимо всего прочего инструкции декодирования. Изучите защиту внимательно еще раз, и вы поймете, что это так. Внешне расшифровщик очень прост. Пара чисел а и b расшифровывается как целая часть от а/Ь. Но если b равно нулю, тогда а интерпретируется как указатель на следующую расшифровываемую инструкцию. Т.е. декодер может "прыгать блохой" и одновременно разжимать текст, фактически реализуя LZ-pac-паковку. Дешифровщик и распаковщик в одном флаконе и в семи ассемблерных командах — не правда ли, результат, которым можно гордиться?
Впрочем, проблему можно решить эмуляцией исключительной ситуации, т.е. перед выполнением деления проверять, не равен ли делитель нулю, и если равен, вызывать обработчик "безопасной" командой jmp. Поэтому необходимо позаботиться о собственной верификации кода — с тем чтобы затруднить его модификацию.
Замечу, что приведенный фрагмент защиты был разработан специально для Win32 и успешно работал в Windows NT- Под NT существует немного отладчиков и все известные мне (по крайней мере на момент написания книги) перехватывали исключение деления на нуль и блокировали работу программы,
На этом рассмотрение 8086 процессора и отладчиков реального режима будем считать завершенным. Бессмысленно перечислять остальные их недостатки, исправленные в существующих сегодня версиях. Крайне маловероятно, что эти знания могут кому-нибудь пригодиться.
– Конец работы –
Эта тема принадлежит разделу:
На сайте allrefs.net читайте: "NAG SCREEN"
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Приемы против отладчиков реального режима
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов