ZX-Ревю 1992 №5-6 1991 г.

Защита программ - продолжение цикла статей по защите программ. (Начало см. стр. 9-16, 53-60)


ЗАЩИТА ПРОГРАММ

Продолжение. (Начало см. стр. 9-16, 53-60)

Глава 4. Прочие приемы защиты.

4.1 Запуск программ в кодах.

О том, как запустить программу в машинных кодах, наверное, знают все пользователи "ZX SPECTRUM". Эта информация изложена во всех справочниках по данному типу компьютеров.

Вкратце напомним основные положения данной системы команд.

Для вызова подпрограмм в машинных кодах используется функция USR, составленная из ключевых слов английского языка:

User SubRoutine

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

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

Нас интересует случай применения USR для вызова подпрограмм в машинных кодах. Для запуска данной подпрограммы USR используется с ключевым словом Бейсика RANDOMIZE или PRINT. После комбинации этих слов указывается цифровая величина, например:

90 RANDOMIZE USR 30000 100 PRINT USR 45000

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

Результат функции USR - значение, находящееся в паре регистров BC микропроцессора. Комбинация ключевых слов RANDOMIZE USR или RESTORE USR только запускает подпрограмму, тогда как PRINT USR еще и индицирует содержимое пары регистров BC на экране.

Фактически, это достаточно широко известная информация и на ней не стоило бы останавливаться, если бы не одно но:

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

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

Выше были рассмотрены команды, достаточно широко известные и наиболее часто применяемые. Чуть реже встречается комбинация LET A = USR 30000

Фактически эта команда полностью аналогична рассмотренным выше - она запускает подпрограмму в кодах с адреса, указанного в функции USR - в данном случае, с адреса 30000. Любопытно, что эта комбинация достаточно широко используется при работе со встроенным калькулятором "СПЕКТРУМа". (Для тех, кто интересуется этим более подробно, рекомендуем изучить трехтомник "ИНФОРКОМа" по программированию в машинных кодах, где это применение описано более подробно).

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

В частности, если Вы подадите команду: GO TO USR 30000

то выполнение команды осуществится аналогично RANDOMIZE USR 30000

Среди таких модификаций команды RANDOMIZE USR следует отметить еще ряд команд, в частности:

LIST USR

и

CLOSE# USR

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

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

Когда мы просматривали дампинг одной из программ, вскрытых Биллом Гилбертом, то обнаружили достаточно любопытную комбинацию символов. После номера строки следовало: CLOSE # USR 0

и т.д.

Сначала мы приняли эту последовательность символов за начало программы в машинных кодах, размещенной в Бейсике. В самом деле, эта последовательность не несла в себе никаких информационных признаков о командах Бейсика. Но в то же время, если бы это было начало подпрограммы в кодах, то первым должен был бы следовать символ REM, поскольку именно после него размещается подобного рода код. Это заставило нас более внимательно проанализировать данную строку и секрет был быстро разгадан.

Естественно, эта комбинация свидетельствовала о начале подпрограммы в машинных кодах, но не думайте, что она была равнозначна команде RANDOMIZE USR 0

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

4.2. Защита, основанная на использовании вариаций числа PI вместо

цифровых констант.

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

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

В частности, Вам необходимо изменить содержимое ячейки 30000, сделав его равным 150.

Традиционно данная команда выглядела бы следующим образом:

10 POKE 30000, 150

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

Поясним вышеизложенное на примере, чтобы заменить адрес традиционным способом, нам пришлось бы вводить еще одну строку программы

10 LET A1 = 30000

20 POKE A1,150

Но этого можно избежать, если задать переменную A, подав команду с клавиатуры:

LET A = 30000

После этого значение переменной A будет занесено в память компьютера и мы сможем вызывать его по мере необходимости. Одно условие - это значение будет уничтожено, если Вы подадите команду RUN, т.к. эта команда полностью освежает буфер переменных. Для запуска Вашей программы необходимо использовать функцию GO TO. Следует отметить один нюанс - автозапуск программы по команде LINE N (со строки N) осуществляется функцией GO ТО N, поэтому Ваше значение будет сохранено в памяти компьютера.

Другой аспект проблемы - это использование вместо числа 150 его кодового слова среди символов символьного набора компьютера. В частности, символу 150 соответствует графический код "G". Следовательно, если Вы используете команды:

LET A = 30000

10 POKE A, CODE "G"

- (используется символ графики), то это будет полностью аналогично первой строке программы в этой статье. Кроме функции CODE можно использовать и производные функции PI:

NOT PI - равноценно 0

SGN PI - равноценно 1

INT PI - равноценно 3

Значения, которые не находят эквивалента в производных PI могут быть образованы с использованием различных комбинаций, в частности:

6 = INT PI + INT PI

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

LET USR = 30000

10 POKE USR, SGN PI

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

4.3 Ключевые слова Бейсика в "хэдере".

Одним из наиболее любопытных приемов защиты, шокирующим начинающих пользователей "СПЕКТРУМа", является использование управляющих кодов в хэдере. Но не менее интересным приемом является использование в хэдере ключевых слов Бейсика. Эта тенденция просматривается во многих программам и позволяет сэкономить и без того

скудное пространство хэдера с целью создания полноценного названия.

Поясним вышеизложенное на примере.

Тем, кто внимательно ознакомился с главой II данного пособия, наверняка известен тот факт, что в хэдере содержится всего 10 символов, отведенных под имя программы. При использовании управляющих кодов количество свободных символов сокращается. Однако, если Вам хочется иметь полноценную заставку - заголовок, то одним из методов, позволяющим совместить это желание с желанием использования управляющих кодов, является применение в хэдере ключевых слов Бейсика.

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

Рассмотрим любопытный пример - название программы "GAME OVER". Его можно было бы написать и по отдельной букве, но тогда это не дало бы возможности использовать в хэдере управляющие коды, которые в моем варианте уничтожают после загрузки на экране слово PROGRAM. Для экономии места здесь используется оператор Бейсика OVER. Среди остальных, известных мне названий программных файлов, приведу наиболее распространенные, использующие ключевые слова Бейсика:

"MVS FORMAT"

"MDS FORMAT"

"В^. FORMAT" - используется Биллом Гилбертом.

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

Следует отметить, что использование ключевых слов Бейсика в хэдере несколько лет назад еще использовалось для защиты программ от копирования. Когда копировщик считывал название программы, то он не мог распознать символ ключевого слова Бейсика и это вызывало сбой в его работе. Однако, последние модели копировщиков уже избавлены от этого недостатка.

4.4 Мерцающий заголовок.

Многие из читателей наверняка пользовались программой COPY-COPY. И, вероятно, обращали внимание на тот факт, как интересно там организован хэдер.

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

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

Итак, вкратце рассмотрим, как работает данный хэдер. Для тех,3

В программе COPY-COPY символы в заголовке имеют следующую последовательность

18 - управление FLASH 1

255 COPY

6 - PRINT запятая 2 0

1 - управление INVERSE

255 COPY

0

8

В данном случае набор этих символов следует рассматривать, как определенную программу, предписывавшую компьютеру определенные действия. Рассмотрим, какие команды будет выполнять компьютер в данном случае.

Теоретически наш хэдер должен был бы появиться на экране (имеется в виду название программного файла) в виде печатных символов, но в данном случае здесь нет таковых. Первая пара символов 18 и 1 - это под управление FLASH и соответственно значение, устанавливающее режим мерцания. Далее следует символ COPY, который распечатывается на экране и начинает мерцать. После этого следует управляющий код 6 -т.н. PRINT-запятая, которая перемещает курсор в следующую половину экрана, аналогично запятой, использующейся в операторе PRINT. Следующая пара символов устраивает значение INVERSE - в данном случае включает инверсный режим. Теперь мерцание второго символа "COPY" будет находиться в противофазе с мерцанием первого, что и создает эффект попеременного мерцания.

Чтобы создать такой хэдер на компьютере, Вам необходимо создать строку выгрузки в Вашей программе. В ней должны находиться операторы SAVE "название" и т.п. Причем вместо управляющих кодов должны стоять пробелы. После этого Вам надо получить дамп памяти по одной из предложенных в главе 2 программ и определить местонахождение заголовка. После этого Вы засылаете в эту область памяти последовательность цифр, которая приведена выше. Естественно, приноровившись, Вы сможете создавать и более оригинальные комбинации, в частности, например, попробуете убрать слово PROGRAM или разместить заголовок в другой точке экрана. Для этого Вам необходимо внимательно изучить раздел "Управляющие коды" главы II данной работы.

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

4.5 Метод защиты, основанный на смещении программ в кодах при попытке

взлома программ.

Если читатель внимательно изучил все материалы, изложенные выше, то он приобрел достаточно высокий уровень подготовки для защиты своих программ. Тем не менее, поработав с ними длительное время, он начинает осознавать, что многие из приемов, применяемых им, достаточно широко известны в сфере программистов для "ZX SPECTRUM".

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

1) Создавая свои сугубо оригинальные приемы;

2) Создавая новые комбинации из уже известных приемов, улучшающие качество и надежность систем защиты;

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

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

Безусловно для Вас такой метод является самым удобным, но не менее удобным он является и для взломщика. Ведь фактически в такого рода программах ему даже не приходится искать адрес начала подпрограммы в кодах - первая строка Бейсика начинается с фиксированного адреса оперативной памяти, на который указывает системная переменная PROG и без подключенной периферии и умышленных изменений значение, находящееся в этой паре байтов указывает на адрес 23755. Соответственно, для нахождения адреса размещения такой подпрограммы достаточно к этому значению прибавить 5 (эти 5 байтов включают в себя номер и длину строки - по два байта на каждый параметр соответственно - и код оператора REM). Кроме этого значение адреса начала подпрограммы можно узнать из значения, стоящего после RANDOMIZE USR или его вариаций.

Одним из выходов является создание "плавающей" подпрограммы в кодах и задание "фальшивого" адреса старта данной подпрограммы.

Рассмотрим более подробно каждый из методов.

Как Вам уже вероятно известно, Бейсик-интерпретатор размещает строки программ последовательно. Т.е. если у Вас есть строки с номерами 5 и 10 и Вы хотите ввести строку с номером 7, то интерпретатор Бейсика разместит эту строку между строками 5 и 10. Когда он будет делать это, то строка с номером 10 переместится в более старшие адреса области ОЗУ, причем ее старое местоположение будет отличаться от нового на длину строки 7.

Теперь представьте, что строка с номером 10 - это строка, в которой расположена наша подпрограмма в кодах, а строки 5 и 7 на начальном этапе отсутствуют. Таким образом, после формирования данной строки с машинными кодами после оператора REM нам необходимо сместить ее в верхние адреса ОЗУ. Для этого все команды управления на Бейсике размещаем в строках, находящихся выше строки с подпрограммой в машинных кодах. (Для того, чтобы найти адрес начала подпрограммы в кодах, Вам придется использовать метод распечатки дампинга памяти, который будет подробно рассмотрен в конце этой статьи).

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

PROG Адрес начала Бейсика.

- Сюда указывает

системная переменная PROG.

В этой области находятся строки Бейсик-программ, которые осуществляют запуск подпрограмм в кодах.

Здесь находится подпрограмма в кодах.

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

Теперь перейден ко второй части проблемы. Нам необходимо скрыть адрес начала подпрограммы в кодах. Здесь мы используем комбинирование уже известных методов для создания очень интересного эффекта.

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

Итак, для начала Вам необходимо полностью оформить аппарат Бейсика, т.е. создать строки программы, которые бы выполняли необходимую Вам операцию. Естественно, все они должны иметь номер меньший, чем строка, в которой находится подпрограмма в кодах. Среди команд, помещенных в этих строках, обязательно должна быть команда запуска подпрограммы в кодах, причем номер, на который указывает RANDOMIZE USR (выгоднее применять разновидность этой команды - раздел 4.1) может быть произвольным. Обязательным условием является лишь то, чтобы он содержал не менее 5 знаков (и не более), т.е. например, запуск осуществлялся бы командой RANDOMIZE USR 25000. Это связано с тем, что при замене этого номера на истинный, который мы будем находить в следующей операции нашего алгоритма, программа в кодах может сместиться, из-за разного количества символов в номере.

После того, как Вы это сделали, нам необходимо будет зарезервировать место под управляющие коды, используя оператор REM. Всего у нас будет использоваться 4 байта INK CONTROL, значение цвета INK, PAPER CONTR и значение цвета PAPER.

Для этого в первой идущей в Вашей программе строке необходимо установить REM и три произвольных символа. Оператор REM устанавливается перед первым идущим в строке оператором.

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

Следующим шагом мы как раз и установим точное местонахождение программы. Для этого в самом конце Бейсика разместим программу распечатки дампа памяти.

9997 FOR I = 23755 TO 64000

9996 PRINT I; TAB 7; PEEK I; TAB 12; CHR PEEK I

9999 NEXT I

Сразу же следует оговориться, что программа может останавливаться по ошибке

INVALID COLOR - неправильный цвет

NUMBER TOO BIG - большое целое число и т.п.

В этом случае Вам необходимо подать команду с клавиатуры:

NEXT I

и распечатка продолжится.

После того, как Вы стартуете данную программу командой GOTO 9997, Вы получите распечатку в следующем формате:

символьное значение содержащееся в этой ячейке памяти

Номер десятичное значение

ячейки содержащееся там памяти

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

1) Номер ячейки, где находится оператор REM, после которого следуют 4

зарезервированных под управляющие коды байта.

2) Номер ячейки, в которой содержится первая цифра числа, находящегося после RANDOMIZE USR.

3) Адрес ячейки, с которой начинается Ваша подпрограмма в кодах.

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

Когда это Вами сделано, Вам необходимо это число "фальсифицировать".

Как Вам уже вероятно известно, в "ZX SPECTRUM" в памяти числа хранятся дважды -первый раз значение, которое печатается на экране, а второй раз - в пятибайтном формате, расположенное после кода 14. В данном случае нам необходимо изменить именно первое значение, которое будет распечатываться на экране.

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

Следующим пунктом нам необходимо скрыть листинг данной программы. Для этого сделаем одинаковым цвет чернил и бумаги с помощью управляющих кодов. Например, мы хотим, чтобы это был белый цвет. Тогда нам необходимо последовательно заслать в ячейки памяти, адреса которых мы получили в пункте 1, следующие значения:

16 - изменение INK

7

17 - изменение PAPER

7

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

Теперь Ваша программа защищена от просмотра командой LIST. Осталось удалить последние строки, осуществлявшие дампинг памяти. Сделайте это, подав команды

9997 ENTER

9998 ENTER

9999 ENTER

Теперь рассмотрим, какие новые качества получила наша защита после такой комбинации.

Если мы вызовем первую строку программы, в которой заложены управляющие коды, для редактирования и уничтожим эти коды командой DELETE, то теоретически мы увидим адрес начала программы в кодах - практически же Вы знаете, что это значение будет неправильным. Но, даже если Вам и удастся определить правильный адрес старта данной подпрограммы в кодах, просмотрев через PRINT PEEK то, что стоит после кода 14, Вам все равно не удастся ее правильно дисассемблировать, поскольку Вы уничтожили управляющие коды командой DELETE, то есть уменьшили размер первой строки на 4 байта и, тем самым, сместили адрес начала данной подпрограммы.

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

Том 2. "Техника взлома компьютерных программ ZX-SPECTRUM. "

Глава 1. Введение

Компьютеры "ZX-SPECTRUM" были разработаны в Англии и поэтому многие пользователи в нашей стране сталкиваются с трудностями освоения программ. Это касается не только проблем языкового барьера. Трудности, связанные со слабым знанием английского языка в большинстве случаев решаются за счет его изучения самим пользователем, потому что без определенного уровня достаточно проблематично осваивать интересное программное обеспечение. Но, кроме барьера языкового, существует и барьер программной защиты. Ведь многие пользователи, проработав определенное время с программой, желают залезть к ней в "нутро" и осуществить какие-либо изменения. Это могут быть изменения, направленные на русификацию программы, изменения, направленные на адаптацию программы под требования пользователя или же просто просмотр с целью изучения приемов программирования. Кроме этого, существует проблема с копированием некоторых защищенных программ, копирование которых невозможно осуществить без определенного уровня подготовки, а также исследования конкретной структуры защиты данной программы.

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

Общие рекомендации.

Если Вы внимательно изучили т. 1, то теперь Вам известны основные принципы защиты компьютерных программ, и, несмотря на то, что техника защиты постоянно совершенствуется, все, что создается отвечает известному Вам принципу: "Все новое - это хорошо забытое старое". А это значит, что все новые приемы защиты являются модернизацией уже известных.

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

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

После того, как Вы определились в цели взлома, Вам необходимо подумать о том, как наиболее рационально загрузить программу, чтобы наиболее быстрым способом обезвредить защиту.

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

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

Структура фирменной программы.

Когда Вы загружаете какую-либо игровую программу, то перед тем, как пойдет загрузка, Вы набираете с клавиатуры команду LOAD "".

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

В течение первых 1-2 секунд считывания мы видим на экране широкие красные и синие полосы, а также слышим длительный однотонный звук. Это так называемый пилот (или пилоттон, или просто тон), который позволяет компьютеру синхронизироваться с сигналом с ленты, с которой он будет считывать программу, что обеспечивает надежность ввода и вывода кодов в память компьютера. (Как Вам уже вероятно известно, все программы состоят из кодов. Бейсик-программу также можно представить, как последовательность кодов), затем появляются мерцающие тонкие желтые и синие полоски, свидетельствующие о том, что компьютер считывает в память байты информации. Первый раз эти желто-синие полосы мерцают кратковременно, поскольку компьютер считывает в память заголовок. Этот заголовок (так называемый "хэдер") и содержит в себе всю информацию о последующем загружающемся блоке кодов и имеет размер всего 17 байтов. Поскольку у нас считывается Бейсик-файл, то появляется надпись "PROGRAM", но возможно появление и других надписей, в частности:

BYTES - байты (коды);

CHARACTER ARRAY - символьный массив;

NUMBER ARRAY - числовой массив.

После этой надписи будет стоять название программы.

Теперь после небольшого перерыва начнется второй пилоттон, а после него считывается собственно сама программа.

Если мы подавали команду LOAD "", то у нас загружался Бейсик-файл и после загрузки компьютер поступает в соответствии с данными, поступившими из хэдера. Для Бейсик-программы это может быть либо автостарт программы со строки n (если программа была записана на магнитофон командой: SAVE "название " LINE

либо остановка в ожидании команды RUN.

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

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

Естественно, следующим этапом нашим совместных исследований должно стать рассмотрение приемов вскрытия данного Бейсик-файла.

Небольшая историческая справка.

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

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

информация о загружающемся после него блоке.

Таким образом, структуру первых программ для "ZX SPECTRUM" можно представить, как совокупность Бейсика и машинных кодов. Машинные коды составляли саму программу, в то время как Бейсик осуществлял загрузку этих кодов в память компьютера, после чего осуществлялся их запуск из Бейсика с использованием функции USR. Таким образом, Бейсик состоял из совокупности команд LOAD "" CODE которую завершала функция USR (Автор не включает сюда все разнообразие текстовой информации, которая выводилась на экран с использованием оператора PRINT). Взлом таких программ с целью изучения вообще являлся личным делом. В последовательность команд Бейсика вводится оператор STOP между совокупностью команд LOAD "" CODE и функцией USR, после чего программа в необходимом для Вас месте останавливалась, и Вы могли беспрепятственно исследовать как структуру, так и содержание самой программы. Фактически мы можем сказать, что эти программы не были защищены, что трудно сказать о более поздних фирменных разработках. Несмотря на все разнообразие появившихся типов защит, мы можем выделить два направления защиты в области загрузки. Это загрузка с хэдером и загрузка без хэдера.

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

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

- создание необычных эффектов в ходе загрузки;

- перемещение загруженного блока кодов в другое место памяти, чтобы обеспечить защиту;

- выполнение этих функции одновременно.

Наглядным примером первого типа являются программы MIKKI и KUNG FU второго типа GREEN BERET и третьего - BOMB JACK.

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

Применение загрузки без хэдера становится возможным благодаря знанию встроенных процедур "ZX-SPECTRUM". В частности, чтобы вызвать встроенную подпрограмму загрузки, Вам необходимо внести в регистровые пары HL и ВС соответственно адрес, с которого начинается загрузка кодов и их длину, а также соответствующий образом изменить содержимое аккумулятора, после чего вызвать подпрограмму в кодах.

(Очень подробно встроенные процедуры описаны в книге YAN LOGAN, FR. O'HARA "THE COMPLETE SPECTRUM ROM DISASSEMBLY", 1983, а также информацию о процедурах загрузки можно получить в ZX-РЕВЮ N5,6 1991г.)

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

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

покажет Вам из каких блоков состоит Ваша программа.

В копировщике ZX COPY 87, TF COPY и им аналогичным хэдер можно отличить достаточно легко потому, как именно в нем содержится информация о том, что это либо Бейсик, либо коды и т. д., а также само название файла. Разумеется, в копировщике Вы можете подробно изучить лишь стандартный хэдер, в то время как нестандартный подобному исследованию не поддается.

Структура хэдера.

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

(Любопытно, что несколько лет назад появился оригинальный метод защиты программ от копирования. Он заключался в том, что в название программы наряду с обычными символами включались и ключевые слова Бейсика, либо управляющие коды. После загрузки этого "фальшхэдера" в копировщик, копировщик не мог распечатать эти символы и работа программы останавливалась с сообщением об ошибке. Великолепный комплект польских копировщиков ZX COPY 87, TF COPY, TF COPY 2, MR COPY и др. практически полностью свел на нет все усилия в данной области защиты. Интересным напоминанием этого направления защиты от копирования может служить программа GREEN BERET. Один из файлов которой длиной 17 байт как раз и должен был выполнять роль фальшхэдера.

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

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

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

Длина заголовка 19 байтов, а не 17, как написано в большинстве книг, но только 17 должны быть активны, поскольку "LOAD" (эта информация аналогична и для "SAVE") первый и последний байты определяют сами. Первый байт для заголовка всегда равен нулю, а последний - "байт четности" генерируется стандартной процедурой SAVE и потому нас не интересует.

Байт 2 содержит число, характеризующее тип записи, в зависимости от того, какое здесь содержится значение, компьютер определяет структуру файла, следующего за хэдером:

0 - это Бейсик-программа

1 - числовой массив

2 - массив символов

3 - блок кодов

Байты 3-12 содержат в себе имя программы

Байты 13 и 14 - длина основного блока (например для Бейсик программа это разность того, что содержится в системных переменных ELINE и PROG.

Байты 15 и 16 - начальный адрес загрузки кодов или номер строки автостарта для программ, написанных на Бейсике.

Байт 16 - для массива данных здесь располагается его имя в следующей форме:

Биты 0-4 - имя (от A=1 до Z=26)

Бит 5 - сброшен, если массив

Числовой бит 6 - активен, если массив

Строковый бит 7 - активен всегда

Байт 17 и 18 - длина Бейсик-программы, т. е. разность того, что содержится в системных переменных VARS и PROG.

Байт 19 - активизируется в ходе работы программ "LOAD" и "SAVE". Для наглядности приведем схему заголовка (см. рис. 1):

Байты 1 2 _ 3...12 _ 13,14 15,16 17,18 19

Флаг

Тип

Имя

Длина

Старт

Длина для

Четность

Бейсика

IX+... 0 1...10 11,12 13,14 15,16 17

Рис. 1 Структура "хэдера"

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

Небольшой комментарий по поводу некоторых байтов хэдера. В зависимости от считываемого блока байты 15 и 16 интерпретируются по-разному. В заголовках программ, написанных на Бейсике, эти байты содержат номер строки, с которой запускается программа, если она была записана с помощью оператора SAVE "ИМЯ" LINE N

Если программа была записана без опции LINE и после считывания не запускается автоматически, то значение этого числа больше 32767. Любопытно, что одним из способов нейтрализации самозапускающихся программ на Бейсике является замена этих двух байтов на число большее 32767 (Подробно этот метод будет рассмотрен в одной из статей Главы 2 под названием "Блокировка автозапуска").

Байты 17 и 18 содержат число, указывающее длину самой программы на Бейсике, т. е. содержимое памяти от байта, указанного системной переменной PROG до байта, определяемого системной переменной VARS. Если мы от всей длины блока (байты 13 и 14) отнимем это число, то узнаем сколько байтов в этой программе занимают переменные Бейсика.

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

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

Сначала программа формирует процедуру в машинных кодах, используя блок DATA строки 30.

Фактически этот блок осуществляет запуск встроенной в ПЗУ подпрограммы-загрузчика, но делает это так, чтобы загружался только хэдер.

При загрузке хэдера в аккумуляторе процессора должен содержаться 0, а в регистре IX адрес, с которого начинает грузиться хэдер. Кроме этого, должен быть включен флаг переноса (флаг C регистра F).

1 REM TAPE EXAMINER 5 CLS:BEEP ,1,24:

PRINT "LOAD A HEADER AND WAIT,PLEASE": PAUSE 150: BEEP ,1,24:CLS 7 RESTORE 10 CLEAR 32511 20 FOR A=32512 TO 32521: READ B:

POKE A, B: NEXT A

30 DATA 175,55,221,33,16,127,205,86,5,201 40 LET B=32528:

DEF FN A(X)=PEEK(B+X)*256*PEEK(B+X+1) 50 RANDOMIZE USR 32512 60 LET C=PEEK B 70 IF C>3 THEN GO TO 50 75 LET B$="":

FOR A=B+1 TO B+10: LET B$=B$+CHR$ PEEK A: NEXT A

78 FOR A=10 TO I STEP -1

79 IF B$(A)=" "

THEN LET B$=B$(TO A-1): NEXT A

80 IF B$=" " THEN LET B$=" "

85 PRINT "FILE NAME: ";INVERSE 1; B$

100 PRINT "FILE TYPE: "

110 GO SUB 1000+100*C

120 PRINT :PRINT

130 POKE B,255

140 GO TO 50

150 STOP

160 SAVE "TAPEXAN" LINE 5: CLS:

PRINT "О. К. REWIND AND PLAY":

VERIFY "TAPEXAN":

CLS:

PRINT "0.K. VERYFIED": STOP 1000 PRINT "PROGRAM" 1010 PRINT "TOTAL LENGTH: ":

FN A(11); "BYTES" 1020 PRINT "PROGRAM LENGTH: ":

FN A(15); "BYTES" 1030 IF FN A(13)>9999

THEN PRINT "SAVED BY: "

'TAB 5; "SAVE ......; B$; ........:

RETURN 1040 PRINT "SAVED BY:"

'TAB 5; "SAVE " " ";

B$; ...... LINE ";FN A(13)

1050 RETURN

1100 PRINT "NUMBER ARRAY" 1110 LET A$=" ": GOTO 1220 1200 PRINT "CHARACTER ARRAY" 1210 LET A$="$"

1220 PRINT "ARRAY LENGTH: ";FN A(11); "BYTES" 1230 LET D=PEEK (B+14)

1240 PRINT "ORIGINAL ARRAY NAME:";CHR$(64+32*(D/32-INT(D/32))) ;A$ 1250 RETURN

1300 IF FN A(11)-6912 AND FN A(13)=16384 THEN PRINT "BYTES-SCREEN$": RETURN 1310 PRINT "BYTES"

1320 PRINT "START ADRESS: ";FN A(13) 1330 PRINT "LENGTH: ";FN A(11); "BYTES" 1340 RETURN 1350 CLEAR:

SAVE "TAPEXAM" LINE 5: BEEP .1,24:

PRINT AT 10,0: "O.K. REWIND AND PLAY TO VERIFY ":

VERIFY "TAPEXAM":

CLS:

BEEP ,1,24: STOP

Листинг ассемблера программы в кодах, которая содержится в строке 30 DATA.

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

Глава 2. Блокировка автозапуска.

Введение.

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

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

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

Мы думаем, что ознакомившись с этими концепциями более подробно. Вы выберете для себя ту, которая наилучшим образом удовлетворяет Вашим потребностям.

2.1 Загрузка Бейсика через блок кодов.

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

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

- Бейсик-файл загружается в память компьютера начиная с адреса, задаваемого системной переменной PROG, блок кодов же загружается с адреса, указанного в хэдере.

- Бейсик-файл обрабатывается интерпретатором как определенная последовательность символов-кодов Бейсика. Блок кодов обрабатывается процессором как последовательность кодов Z80.

На этом свойстве этих файлов и основан данный метод взлома. В самом деле, нам ничего не стоит обмануть компьютер - он думает, что загружает в память файл кодов, а на самом деле загружает файл Бейсика и при этом он не сможет установить никакой ошибки. Поскольку при той проверке, которую осуществляет "ZX SPECTRUM", такую ошибку установить просто-напросто невозможно.

Итак, рассмотрим этот метод более подробно.

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

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

7F00

XOR A

7F01

SCF

7F02

LD IX,7F10

7F06

CALL 0556

7F09

RET

Обычно в копировщике мы можем наблюдать следующую картину (рис. 2):

Имя программы

Тип программы

Строка автозапуска

Длина

xxxxxxxxxxx

P

10

423

yyyyyyyyyyy

C

35000

22250

zzzzzzzzzzz

C

61200

1800

Рис. 2

После имени программы обычно появляется сообщение о типе данной программы: PROGRAM, CODE и т. п.

Строка автозапуска появляется только для программ Бейсика (для кодов же появляется номер ячейки памяти, с которого начинается загрузка). В разделе "длина" появляется длина загружаемого вслед за хэдером файла, это не длина хэдера.

Нам в нашей работе понадобится "реальная длина" (В большинстве случаев это значение не совпадает со значением "длина" в хэдере, но бывают и исключения). Кроме этого Вам необходимо запомнить номер строки автозапуска.

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

Для создания такого хэдера нам понадобится значение "реальной длины" файла, взятое из кодировщика. Теперь запишем на ленту этот хэдер кодов командой с клавиатуры: save "имя файла" code 30000, реальная длина

В графе "имя файла" Вам необходимо будет написать произвольное название файла по Вашему выбору, но не более 10 символов. Значение 30000 после CODE означает, что файл кодов, загружающийся после этого хэдера, будет загружаться с ячейки памяти 30000 (это же касается и записи информации т.е. после подачи данной команды, на ленту, должен будет записаться блок длиной "реальная длина", начиная с ячейки памяти 30000. Однако, поскольку нам необходим только хэдер, мы не будем дожидаться выгрузки на ленту файла кодов) и выключим магнитофон.

Теперь мы имеем следующие магнитофонные блоки:

Исходный хэдер (1) Бейсика

Файл Бейсика (1')

Специальный хэдер кодов (2)

Этот хэдер мы имели вместе с блоком Бейсик программы, длина хэдера 19 байт.

Этот файл описывался исходным хэдером и загрузить в компьютер автозапуском.

Этот хэдер мы создали таким образом, чтобы он описывал файл Бейсика как файл кодов. Длина=19 байт

Теперь нам необходимо непосредственно осуществить подмену. Для этого подадим команду с магнитофона:

LOAD "" CODE

после которой загрузим созданный нами хэдер. После этого хэдера Вам необходимо загрузить файл Бейсика (1'), однако этому файлу не должен предшествовать исходный хэдер (1). (В данном случае этот исходный хедер (1) не загружается вообще). Наилучшее техническое решение, позволяющее точно найти файл Бейсика (1'), пропустив исходный хэдер, является временное выдергивание шнура загрузки из магнитофона совместно с использованием клавиши ПАУЗА магнитофона (если такая имеется).

Итак, Вы осуществили подмену и загрузили Бейсик-файл под видом кодов. Теперь Вашей задачей является просмотреть этот файл и изучить его структуру.

(Продолжение следует.)




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Книга - Тайники ZX-Spectrum: Ошибки в Системе.
Interface - elph: games, i haven't played.
Избранный народ - взгляд на мир через призму разноцветных окошек.
Боль - Случайно я встретился с ней, звали ее FREEDA, увы! Где есть талант, там всегда есть проблемы. Я не любил ее, она не любила меня...
Курьер SF - Новости от издательств.

В этот день...   24 апреля