рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Простейшие системы шифрования

Простейшие системы шифрования - раздел Компьютеры, История хакерства — Высказана Мысль Или Нет, Она Существует И Имеет Свою Власть,— Сказал Тус...

Высказана мысль или нет, она существует и имеет свою власть,— сказал Туск. — Ты можешь обнаружить однажды, что грань между жизнью и смертью у Свободных, слишком тонка."

Ф. Херберт. "Дюна".

Данная глава является кратким обзором проблемы для неподготовленного читателя. Остальные могут ее смело пропустить.

Неоправданно популярный способ проверки легальности копии:

If (!IsValidUser())

{

Message ("Invalid user! Aborting. ..");

Abort;

}

транслируется компилятором приблизительно в следующий код;

CALL IsValidUser

OR AX,AX

JZ continue

push offset str_invalid_user

CALL Message

CALL Abort

continue: ; нормальное продолжение исполнения программы

и может быть легко взломан хакером изменением всего одного байта. Поменяв выделенную строку JZ continue на JMP continue, злоумышленник получает работоспособную копию программы. Независимо от алгоритма функции lsValid-User — будь то проверка ключевого диска или ввод серийного номера — совершается безусловный переход на ветку нормального продолжения исполне­ния программы. На языке Си исправленная программа будет выглядеть так:

IsValidUser();

if (!true)

{

Message(“Invalid user! Aborting..,");

Abort;

}

T.e. ветка {...} никогда не получит управления! На самом деле все не так просто, поскольку в исполняемом файле нужно еще найти эту инструкцию перехода. К тому же разработчики защиты это всячески пытаются затруднить. Запутывают алгоритм, используют самомодифицирующийся код, применяют не­документированные вызовы операционной системы... Однако такие препятствия хакера не смущают. Технологии противодействия заметно обгоняют эволюцию систем защиты. А с появлением дизассемблера IDA, отладчика Soft-Ice и распа­ковщика сир386 копание в чужом коде не только превратилось ц удовольствие, но и стало доступно широкому кругу лиц. Десять лет назад всего выше перечис­ленного богатства еще не было, процессор работал только в реальном режиме, и не было никакой возможности уберечь отладчик от разрушающего воздействия со стороны изучаемой программы. Хакеры "старого поколения" работали в основном карандашом, листком бумаги и головой. Зачастую код приходилось дизассемблировать в уме, а недокументированные вызовы изучали, погружаясь в недра операционной системы. Это не только требовало высокого профессионализ­ма, но и огромного количества свободного времени, которое было нечем занять.

Россия в этом преуспела. Кадровые специалисты, скучавшие на работе, восприняли защиты как увлекательную головоломку. Так или иначе, с той поры мы настолько привыкли к бесплатному поломанному программному обеспечению, что до сих пор поддаемся соблазну купить пиратский диск, а не платить вдесятеро большую сумму фирме-производителю.

Отсюда и возникло твердое убеждение: как бы разработчик ни защищал свой продукт, все равно сломают. На самом же деле существуют алгоритмы, делающие взлом по меньшей мере неэффективным. Основанные на криптографии, они обеспечивают не только надежную, но и математически обоснованную степень защиты.

Допустим, пароль, введенный пользователем, расшифровывает рабочий код программы. Мне могут возразить, что это не спасает от банальной кражи пароля. Что помешает одному пользователю использовать пароль другого? Но если пароль взят из неочевидных источников, например электронных ключей, взлом стано­виться трудным делом.

Кроме того, даже использование в качестве пароля ключевого диска или файла требует по крайней мере одной легальной копии для взлома. Пока такая копия попадет к руки хакера и будет нелегально распространена, разработчик успевает продать достаточное число экземпляров продукта. Кроме того, каждый уважающий себя кодокопатель считает долгом чести самостоятельно написать генератор ключей, а не использовать уже существующий. Это позволит какое-то время поддержать объем продаж.

Впрочем, организационные проблемы выходят за рамки данной книги, и мы на этом закончим их рассмотрение. Гораздо интереснее рассмотреть популярные криптосистемы и возможные атаки на них.

Большинство защит сегодня используют шифровку своего кода в целях затруднения анализа и модификации кода. Ключ, используемый в расшифровщи­ке, хранится непосредственно в последнем, поэтому теоретическая криптостой-кость подобной системы равна нулю. Впрочем, это не важно, так как преследу­ются совсем другие цели. Кроме IDA, ни один известный мне дизассемблер не может работать с шифрованным кодом. Отладчик не сможет функционировать, если декодер использует необходимые ему ресурсы. Наконец, непосредственная модификация кода становится невозможна. При этом сам алгоритм шифра и его криптостойкость не играют никакой роли! Действительно, если пароль, использу­емый декодером, известен, то использовать криптостойкие алгоритмы бессмыс­ленно!

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

а хог b хог а= b.

Для этого просто перечислим все возможные значения а и b в следующей табличке:

аb
0 хог 0 хог 0 == 0 0 хог 1 хог 0 == 1
1 хог 0 хог 1 == 0 1 хог 1 хог 1 == 1

Заметим, что хог — битовая операция. Аргументы а и b могут иметь только два значения: 0 или 1. Однако никто не запрещает проводить ту же операцию для последовательности битов. Команда процессора XOR word, const на самом деле представляет собой не word хог const, а последовательность операций над каждой парой битов двух переменных.

Теперь обратим внимание, что а хог 0 == а; а хог 1 == !а. Т.е. значащими в маске шифрования являются только единичные биты. Поэтому рекомендуется выбирать такую маску, в которой единичные и нулевые биты равномерно переме­шаны. К примеру, 00001111b (OxF) будет плохой маской, так как оставляет неизменными четыре старшие бита в каждом символе шифротекста, что позволя­ет (как будет показано ниже) успешно атаковать шифр. Маска 01010011 полно­стью уничтожает вероятностное распределение исходных символов в шифротек-сте, поэтому считается хорошей.

Возможна шифровка двух видов — статическая и динамическая. В первом случае дешифровщик работает только один раз, после чего исходный текст может быть полностью восстановлен. Иными словами, наступает момент, когда не остается ни одного зашифрованного фрагмента. Такой подход имеет очень про­стую реализацию, но крайне неэффективен. Хакер может снять дамп с памяти в момент окончания работы расшифровщика и записать его на диск. После чего полученный файл можно будет изучать штатными средствами. Это невозможно выполнить для динамической расшифровки, когда ни в какой момент код не будет расшифрован полностью. При вызове процедуры он расшифровывается, а при выходе зашифровывается опять. Технически можно написать декодер, который расшифрует весь код в автономном режиме, но это довольно сложно и требует тщательного анализа защиты.

Покажем это на примере самошифрующейся программы. Традиционно такие программы выполняются на ассемблере, но можно реализовать их на С, Pascal и подобных языках, даже не используя ассемблерных вставок, а работая с памятью через указатели. Рассмотрим простейший пример (file://CD:SOURCE ASM_CCRYPTOOcryptOO.asm).

LEA SI, beginCrypt ; расшифровываем с этого адреса

Repeat:

XOR Byte Ptr [SI],077h ; расшифровать очередной байт

INC SI ; Переместить указатель

СМР SI, offset endCrypt ; ?Конец достигнут

JNA Repeat ; —{SI<=offset endCrypt}—

Чтобы полученная программа оказалась работоспособной, необходимо вруч­ную зашифровать фрагмент [offset beginCrypt, offset endCrypt] по хог 0х77. Для этого можно воспользоваться утилитой HIEW, скриптом IDA или написать процедуру, которая это сделает автоматически.

Теперь сравним два дампа: до и после шифровки. Шифровка исказила исходный дамп до неузнаваемости, исчезла текстовая строка "Hello.World!". Этот прием может использоваться злоумышленником для сокрытия текстовых фраг­ментов в вирусах, троянских программах и т.д.

Шифровка затруднила к изучение программы. Вот что выдаст дизассемблер в нашем случае.

1AEF:0100 BE0D01 MOV SI,0010D

1AEF:0103 803477 XOR BYTE PTR [SI] ,077

1AEF:0106 46 INC SI

1AEF:0107 81FE2401 CHP SI,0124

1AEF:010B 76F6 JBE 0103

1AEF:010D C3 RET ; < отсюда все зашифровано

1AEF:010E 7ECD JLE 00DD

1AEF:0110 62 DB 62

1AEF:0111 76BA JBE 00CD

1AEF:0113 56 PUSH SI

1AEF:0114 B43F MOV AH,3F

1AEF:0116 121B ADC BL, [BP+DI]

1AEF:0118 1B18 SBB BX, [BX+SI]

1AEF:011A 5В POP BX

1AEF:01lB 57 PUSH DI

1AEF:011C 2018 AND [BX+SI] ,BL

1AEF:011E 051356 ADD AX,5613

1AEF:0121 7A7D JPE 01A0

1AEF:0l23 53 PUSH BX

 

Как разобраться в этой дикой мешанине кода и данных? Что делать и как с этим жить?

Тут на помощь приходит уникальный дизассемблер IDA, поддерживающий встроенный Си-подобный язык. Следующий скрипт (file;// CD; SOURCE ASM_CCRYPTOOci-yptOO.idc) выполнит все автоматически. Чтобы его запустить на выполнение, нужно дать команду: idax —ScryptOO.idc cryptOO.com

Рассмотрим, как он работает:

for (a=0x10D,a<0xl24;a++) // Цикл дешифровки

{

c=Byte(MK_FP, (0x1000,a)); // Взять байт

с = с ^ 0х77; // Расшифровать

PatchByte (MK_FP(0x1000,a),c); // Записать результат

}

Фактически мы копируем алгоритм расшифровщика, с точностью до реализа­ции. Приведенный код расшифровывает загруженный образ файла, который потом IDA будет в состоянии дизассемблировать. Вот за эту возможность он горячо любим всеми хакерами. В самом деле, не нужно выходить из уютной и привычной среды дизассемблера в агрессивную среду отладчика. Дожидаться окончания расшифровки и записывать дамп на диск (а ведь не всякий отладчик обеспечивает такую возможность). Загружать полученный образ в дизассемблер и, если что-то не ладится, повторять все вновь.

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

Для начала нам потребуется узнать начало и конец зашифрованного фрагмен­та. Переключим HIEW в режим дизассемблера н обратим внимание на следующие строки:

00000000: BE0D01 mov si,0010D ; <-- начало зашиф. фрагмента

00000003: 803477 xor b, [si],077

00000006: 46 inc si

00000007: 81FE2401 cmp si,00124 ;<-- конец зашиф. фрагмента

0000000В; 76F6 jbe 000000003

Поскольку в com-файле базовое смещение 0х100, то истинным адресом начала будет 0x10D ~ 0х100 = 0xD. Переведем курсор на полученный адрес, введем следующий скрипт XOR AX,77 и начнем расшифровку. Код на глазах "оживет" и, словно феникс из пепла, одна за одной возникнут "родные" инструкции. Теперь файл можно сохранить на диск и обработать любым дизассемблером вплоть до debug.com! Вот только работать он больше не будет. Наша ошибка в том, что мы не удалили дешифровщик, который "не знает", что код уже расшифрован и портит его. Достаточно заменить маску шифрования 0х77 на 0х0, чтобы устранить это упущение.

Однако неограниченные возможности IDA позволяют проделать ту же самую операцию и на ее встроенном языке! Для этого нам необходимо воспользоваться файловым вводом-выводом.

while (1)

{

c=fgetc (hIn) ;

if (c==-l) break;

c=c ^ 0x77;

if (fputc (hOut, c) ,hOut)==-l) break;

}

 

Полученный дамп можно загрузить в любой дизассемблер (в IDA. например) и продолжить его изучение. Конечно, тот же самый скрипт не хуже будет обрабатываться и обычным компилятором Си (и даже быстрее выполняться), но это потребует компилятора (которого может и не оказаться под рукой), к тому же IDA в этом отношении просто удобнее. Дело в том, что зачастую анализ алгоритма декодера — далеко не тривиальная задача, и он заметно облегчается, когда в IDA перед глазами возникает его дизассемблированный код. Можно даже не вникать в его смысл, а просто покомандно переписать на Си. В этом отношении IDA не имеет равных.

В некоторых случаях ресурсов и быстродействия встроенного языка явно не хватает, н тогда приходится прибегать к помощи MS VC или оптимизированного ассемблера. Но в таких случаях уместнее воспользоваться другими методами.

Выше я назвал использование отладчика "агрессивным" методом. Б каком-то смысле это метод "грубой силы". Никакого вникания в алгоритм декодера не требуется. Достаточно лишь точно определить момент завершения расшифровки и скинуть дамп в файл. Это очень популярный прием, однако необходимо помнить, что жизнь "человеку с отладчиком" испортить очень легко. Возможны самые разнообразные эффекты — от блокирования трассировки до "глухого" завешивания системы. Выход из этого положения только один: использовать хороший отладчик.

Данный пример не содержит антиотладочных приемов, поэтому для его изучения подойдет любой отладчик. Воспользуемся замечательной утилитой trsutil, входящей в комплект антивируса AVP 2.2 PRO. Это очень компактный, но многофункциональный отладчик, который подходит для решения широкого спек­тра задач. Подробное обсуждение его возможностей впереди, а пока ознакомимся лишь с некоторыми из них.

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

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

Один из мощнейших распаковщиков Сuр386 имеет ручной режим распаковки. По сути это полноценный интегрированный отладчик необычайной мощности. На данном этапе нас это еще не интересует, поэтому выберем простейшую пошаго­вую трассировку, для чего запустим сир с ключами /I cryptOO.com /d. Как нв первом случае, дожидаемся выхода из цикла (для этого можно подогнать курсор к строке OxlOD и нажать F4). В этот момент весь код расшифрован и может быть немедленно исполнен. Если бы существовал способ "сфотографировать" это состояние и записать, чтобы в любой момент можно было его восстановить, не начиная выполнения программы с самого начала... И сир как раз обеспечивает такой снимок! Он позволяет сохранять значение любых регистров и точку входа и сохранять их в ехе-файле. Для его создания необходимо выбрать пункт меню

"Create executable file" и задать длину сохраняемого фрагмента. В нашем примере она равна OxD. Никакие регистры нам сохранять не нужно, поэтому выбираем "Just create, no preserving" и нажимаем заветную кнопочку "ОК". Мы получим готовый работоспособный файл, который можно запускать, загружать в отладчик и дизассемблер в рекордно короткие сроки — на все действия вполне достаточно пяти-десяти секунд! И это при том самом впечатляющем результате, который мы получили!

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

Рассмотрим простой пример динамической шифровки на основе все той же операции xor (file:/ /CD:SOURCEASM_CCRYPT02crypt02.asm).

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

EXECUTE PROC NEAR

CALL CRYPT ; Расшифровываем процедуру

PUSH ВР ; Сохраняем ВР для вложенных вызовов

CALL Word ptr [ВР+2] ; Запускаем расшифрованную проц.

POP ВР ; Восстанавливаем ВР

CALL CRYPT ; Зашифровываем проц. Обратно

RETH ; —

EHDP

Чтобы данный пример мог работать, необходимо каким-то образом сообщить процедуре CRYPT начало и длину шифруемого фрагмента.

Один из вариантов — перед каждой процедурой расположить блок данных, содержащий все необходимые сведения.

СРВ macro Segin,End,XorMask ; CPM (CRYPT PREDEF BLOCK)

DW offset &End - offset &Begin

DW offset &Begin

DB XorMask

endm

Определим для удобства метод run следующим образом:

RUN macro ProcA

MOV ВР, offset &ProcA-5

CALL EXECUTE

endm

Тогда вызов подпрограммы будет выглядеть как run procl. Рассмотрим дизас-семблированный листинг этого вызова:

start proc near

mov bp, 234h

call sub_0_11A

retn

start endp

Процедура sub_0_11A и есть execute, — чтобы в этом убедиться, достаточно бегло взглянуть на нижеследующий фрагмент:

Sub_0_11A proc near
call sub_0_107
push bp

call word ptr [bp+2]
pop bp
call sub_0_107

Интересующая нас процедура находится по адресу [BP+2] == 0х234 + 0х2 = 0х236; [0х236] == 0х239. Однако дизассемблер не может восстановить код процедуры, так как он еще зашифрован.

seg000:0235 dw 239h

seg000;0239 db 0C9h

seg000:023A db 21h

seg000:023B db 75h

seg000:023C db 0DAh

seg000:023D db 7Ch

seg000:023E db 0B7h

seg000;023F db 3

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

Дизассемблирование программы становится невозможным. Как с этим бороть­ся? Можно воспользоваться отладчиком, не это не будет полноценной заменой дизассемблированному листингу. Можно поочередно записывать дампы всех процедур по мере их выполнения, но это очень утомительная и бесконечно долгая процедура. И что потом делать с этой кучей дампов? До недавнего времени дизассемблирование динамических защит было сложным и неэффективным заня­тием, на которое отваживались далеко не все. С появлением IDA все изменилось.

Запустим несложный скрипт на выполнение (file;//CD:SOURCE ASM_CCRYPT02crypt02.idc).

static trн()

{

auto a,p,l,c,mask;

p= ScreenEA(); mask = Byte(p+4); I = Word (p);

for (a-O; a<i; a++)

{

с = Byte(p+a+5);

с - с ^ mask;

PatchByte (p+a+5, c)

}

AnalyseArea (p+5, -1);

}

Наведем курсор на начало блока СРВ и вызовем функцию try. Это еще одна особенность IDA — с помощью своих функций мы безгранично можем расширять ее возможности. Функция try теперь будет доступна из любого выполняющегося скрипта. Или с консоли. Нажмем Shift-F2 и введем try(). Было бы утомительно проделывать это каждый раз, не поддерживай IDA макросы. Можно задать любую удобную для нас горячую клавишу для вызова этой функции. Например, Alt-C.

Однако этот метод грешит тем, что придется проанализировать все функции вручную, а это потребует больших усилий. В самом деле, неудобно работать "ручками" там, где можно использовать автономный скрипт. Попытаемся исполь­зовать тот факт, что процедура EXECUTE принимает входной аргумент в регистре ВР, представляющем собой смещение СРВ. Можно предположить, что использо­валась конструкция MOV ВР, offset Proc (LEA ВР, Ргос), и таким образом, найдя все вхождения MOV ВР, xxxxCALL EXECUTE мы можем автоматически расшифровать весь файл? В большинстве случаев этот способ безотказно сраба­тывает. Действительно, поскольку процедура расшифровки одна, то простым контекстным поиском мы можем обнаружить все ссылки на нее. Неужели все так просто? И все наши усилия по созданию динамически шифрующейся программы пропали даром? Другими словами: можно ли от всего этого защититься? Разуме­ется! Даже не потребуется менять алгоритм. Нужно, чтобы адрес процедуры был задан не в форме константы, а произвольным образом вычислялся. В этом случае контекстный поиск окажется бессильным.

В нашем примере сигнатурный поиск поможет расшифровать только часть процедур, большую часть которых составляют переходники к операционной системе такие как WriteString, ReadString и т.д., не содержащие в себе ни йоты интересного кода. Остальные останутся зашифрованными. Приглядимся повнима-тельнее к тому, как работает функция main:

LEA SI, scenario

Main_repeat:

LODSW

OR AX,AX

JZ main_exit

XCHG BP,AX

SUB ВР, 5

CALL EXECUTE

JMP SHORT Main_repeat

Фактически это встроенный интерпретатор, который последовательно испол­няет инструкции из списка scenario. Но содержит ли scenario полный перечень процедур? Быть может, вложенные процедуры также содержат свой локальный интерпретатор?

Но существует простое и элегантное решение, которое зачастую упускают разработчики защит. В большинстве случаев все существующие процедуры расположены вплотную одна за другой. За концом одной процедуры — начало следующей. Эта банальность предельно упрощает расшифровку. Очевидным решением будет помещение между соседними процедурами случайного числа незначащих байт. К сожалению, ни один из известных мне ассемблеров или компиляторов не поддерживал такой особенности. А вручную это делать очень утомительно? Но, допустим, автор защиты пошел на такие затраты времени и все соседние процедуры разнесены от нуля до N байт. Остановит ли это хакеров? Давайте еще раз внимательно посмотрим на СРВ-структуру:

СРВ macro Begin, End,XorMask

DW offset &End - offset &Begin

DW offset &Begin

DB XorMask

endm

Обнаруживаются две закономерности. Поле [2] численно равно смещению заголовка СРВ и offset &End — offset &Begin, как правило, не больше OxFFFF. Этой избыточной информации вполне достаточно для поиска блоков СРВ и расшиф­ровки всех существующих процедур простейшим автоматическим скриптом.

Сражение технологий взлома и защиты не прекращается ни на минуту. Каждый день рождаются все новые хитроумные скрывающие механизмы, чтобы спустя короткое время исчезнуть, освобождая место для новых. Приведенный выше пример оказался нестойким из-за ошибки в программной реализации. Существуют ли программы без ошибок? Хакеры отвечают: "Программ без ошибок не бывает. Бывает — плохо искали". Неизвестно, чего больше в этой шутке — юмора или правды.

Язык ассемблера, однако сегодня непопулярен. Можно ли писать самошифру­ющиеся программы на языках высокого уровня? Удивительно, но далеко не каждый программист на этот вопрос утвердительно ответит "ДА". Обычно пожимают плечами — зачем это делать? В результате подавляющее большинство программ абсолютно не защищены и легко модифицируются злоумышленниками, число которых угрожающе растет. Доходит до того, что новые версии программ и "ломки" для них появляются практически одновременно, часто их разделяет всего несколько часов.

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

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

К счастью, MS-DOS никак не препятствует модификации программой своего собственного кода, и данная процедура будет успешно работать:

void Crypt (char *point, char *EndPoint)

{

while (Point<=EndPoint) Point[0]=(point++)[0] ^ 0х77;

}

Однако при этом будут наложены жесткие ограничения — программа должна компилироваться для TINY модели памяти. Будет очень жаль, если ваш любимый компилятор на это не рассчитан.

Попробуем выяснить, что влияет на выбор модели памяти. TINY — "крошеч-' ная" — размещает в одном сегменте и код, и данные. Следовательно, один и тот же указатель может иметь доступ как к собственному коду, так и к данным, Отметим, что в языке Си нет указателей, работающих с кодом, и только особенность выбранной модели памяти позволяет "дотянуться" до кода. Впрочем некоторые компиляторы могут проверять границы и при выходе за отведенное для мнных пространство генерировать исключение или останавливаться с сообщени­ем об ошибке.

Модель SMALL размещает код и переменные в двух независимых сегментах. Используются только близкие указатели, адресуемые через DS. Сам DS строго указывает на сегмент данных.

Но с переходом к большой (LARGE) модели памяти все вновь меняется. При этом все указатели превращаются в далекие (сегмент: смещение) и могут адресовать как данные, так и код. Эту замечательную новость омрачает тот 'прискорбный факт, что вместе с указателями становятся далекими и вызовы процедур. В момент загрузки файла DOS вычисляет и непосредственно записы­вает конкретные значения сегментов во всех перемещаемых элементах. Подроб­нее этот процесс описан в руководстве MS-DOS для программиста: мы же просто примем к сведению, что средствами одного лишь языка высокого уровня, не Используя ассемблерных вставок, работать с перемещаемыми элементами невоз­можно.

– Конец работы –

Эта тема принадлежит разделу:

История хакерства

На сайте allrefs.net читайте: "История хакерства"

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Простейшие системы шифрования

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

О чем эта книга
"... В моем уме не оставалось места для беспокой­ства об успехе или провале книги. Было лишь желание работать над ее созданием." Ф. Херберт. "Еретики Дюны". Эта

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

Лаборатория искусственного интеллекта в США и PDP-1
"Нет четкой грани между богами и людьми: одни переходят в других." Ф. Херберт. "Мессия Дюны". Персонал, обслуживавший правительственные компьютеры, отн

Си и UNIX
"Легкие мои вдыхают ветер времени. Дующий над мертвыми песками..." Ф. Херберт. "Дюна". В 1969 г. усилиями двух талантливых программистов была создана си

Конец хакеров шестидесятых
"Я не должна бояться. Страх убивает разум. Страх — малая смерть, которая приносит полное уничтожение. Я смотрю в лицо моему страху..." Ф. Херберт. "Дюна".

RSX-11M
"Подсмотреть будущее — значит украсть мисти­ческий огонь от священного костра." Ф. Херберт. "Дюна". В начале семидесятых еще никто не представлял себе,

Бытовой компьютер восьмидесятых
"Наверняка человеческий мозг, в котором особым способом развиты сверхспособности, делающие его живым компьютером, до сих пор находит применение." Ф. Херберт. "

Рождение современных хакеров, или снова INTEL
"...он был пропозойским творением, рождение и смерть которого по сути одновременны." Ф. Херберт. "Дети Дюны". Однажды руководство IBM предприняло попытк

Психологический анализ. Что движет хакером
"Инструменты управления государством всегда должны быть остро отточены и готовы к упот­реблению. Власть держится на страхе." Ф. Херберт. "Мессия Дюны".

Хеши. Односторонние функции
"Ночь — это туннель, — подумала она. — Это дыра в завтра, если только оно наступит, это завтра." Ф. Херберт. "Дюна". Вся современная криптография основа

F(Ai) —P--->Aj
Разумеется, только для одного-единственного р мы получим исходную после­довательность Aj, а для всех остальных р — "мусор". Каким способом можно удостовериться в том, что полученная Aj и

С—f---Z
Такая операция дает нам неограниченную гибкость. Элементами перечислен­ного множества могут быть литеры, группы литер, а также целые слова. Таким образом, предложенный алгоритм позволяет полностью

Открытые системы
Приведенные выше подходы по существу никакого отношения к криптографии не имеют, поскольку являются закрытыми. Т.е. система содержит в себе и шифротекст и пароль. Утаить пароль в таком случае прост

Как атаковать шифр
При атаке на шифр считается, что криптоалгоритм известен с точностью до реализации и требуется найти пароль. В качестве примера рассмотрим программу crackmeO.com (file://CD:SOURCEA5M_CCRACKmeOCrack

Первый шаг. От ЕХЕ до CRK
Бесспорно, среди существующих на сегодняшний день дизассемблеров луч­шим является IDA. Особенно идеально он подходит для взлома и изучения защищенных программ. Очевидно, что BreakOO не является так

E call j_??4CString@@QAEABVO@PBD[3Z
Обратим внимание на подчеркнутую строку. Насколько же с первого взгляда неочевидно, куда указывает указатель еах! Попутно замечу, что даже сегодня не каждый компилятор способен генерировать такой к

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

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

F:00401624 E805030000 call 0040192E
  Если мы попытаемся заглянуть в процедуру Ох040192Е, то вероятнее всего утонем в условных переходах и вложенных вызовах. Сложность и витиеватость кода наталкивают на мысль, что это б

Перехват WM_GETTEXT
Довольно часто разработчики защит читают содержимое окна, посылая ему сообщение WM_GETTEXT. Это ставит в тупик неопытных кракеров. Установка точек останова на GetWindowsText и GetDIgItemText ни к ч

Ограничение времени использования
Другим популярным ограничением DEMO-версий является ограниченное вре­мя использования. Бывают по крайней мере два вида ограничений. В первом отсчет времени идет от момента первого запуска, а во вто

C2 jnz loc_4011c0
Найти в листинге дизассемблера его можно двояко — среди перекрестных ссылок на RegCreateKeyExA: 0040200С RegCreateKeyExA dd ? или по ссылке на строку aSoftwareCrackO; 004

Ограничение числа запусков
Ограничение числа запусков имеет много общего с защитой по времени с момента первого запуска. Однако теперь вместо начального времени необходимо где-то сохранить счетчик, инкрементирующийся (декрем

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги