ZX-Spectrum изнутри 1969 г.

Глава 5 - защита загрузчиков.


5. ЗАЩИТА ЗАГРУЗЧИКОВ.

Все игры имеют очень хорошо защищенную программу, написанную на
БЕЙСИКе, т.к. это - важнейший (с точки зрения действенности защиты)
элемент всей программы - ведь с БЕЙСИКа начинается считывание всей
программы. Если БЕЙСИКовский загрузчик защищен слабо, то взлом всей
программы значительно облегчается. (Примером этого являются загрузчики
фирмы ULTIMATE, представленные в предыдущем разделе. Одним из спосо-
бов снятия защиты загрузчиков является их считывание с помощью прог-
раммы "LOAD/MERGE" (см. раздел 2). Однако иногда лучше поместить этот
загрузчик не в памяти, предназначенной для БЕЙСИКа, а выше RAMT0P,
чтобы можно было спокойно просматривать его, не опасаясь возможности
случайных изменений в нем.

Для этого имеется очень действенный метод: считывание программы
на БЕЙСИКе к$к блока машинного кода по удобному для нас адресу. Чтобы
добиться этого, требуется знать длину программы, которую мы хотим
считать (можете использовать процедуру "CZYTACZ" из раздела 2), хотя
можно обойтись и без длины. Кроме того требуется немного свободного
места на магнитной ленте. Этот способ основывается на обмане инструк-
ции LOAD путем подмены заголовка.

На свободном месте ленты записываем заголовок блока кода с по-
мощью SAVE "BAS" CODE 30000,750, если знаем, что длина программы сос-
тавляет 750 байт. Если не знаем, то подаем соответсвенно большее зна-
чение - порядка нескольких килобайт или даже десятков килобайт, хотя
программа может иметь всего лишь 100 байтов длины. На ленте записыва-
ем только сам заголовок, прерывая запись после этого нажатием клавиши
"BREAK". Теперь устанавливаем ленту точно перед записанным заголов-
ком, а ленту с программой - сразу после заголовка программы, но перед
требуемым блоком данных. Вводим

CLEAR 29999: LOAD "" CODE
и считываем заголовок. Сразу после его считывания нажимаем STOP на
магнитофоне, заменяем кассету и вновь нажимаем PLAY (все это время
компьютер ждал блок данных). Теперь считывается программа на БЕЙСИКе,
но по адресу 30000 (выше RAMT0P). Если мы указали в заголовке завы-
шенную длину программы, то считывание кончается "ТАРЕ L0ADIND ERROR",
но это не мешает - теперь уже можно смотреть считанную программу лю-
бым способом, даже набирая с этой целью программу на БЕЙСИКе.

Кроме этого метода существует и второй, но для того чтобы им вос-
пользоваться, обязательно знание АССЕМБЛЕРа (а пользоваться стоит, т.
к. он дает большие возможности в раскрытии программ).

Очень часто (особенно в новейших программах) встречаются блоки,
записанные и считываемые в память компьютера без заголовка. Это дос-
таточно оригинальная и эффективная мера защиты обычно отпугивает на-
чинающих, но раскрытие такой программы вовсе не является трудным. Вся
тайна основана на использовании хранящихся в ROM SPECTRUM процедур,
используемых инструкциями LOAD, SAVE, VERIFY и MERGE.

По адресу #0556 (1366) находится процедура LOAD^BYTES, считываю-
щая с магнитофона блок данных или пилот и следующую за ни минформа-
цию. При этом неважно - будет ли это заголовок или требуемый блок
данных, которые следует разместить где-то в памяти.

Начнем асе же с начала. Каждая зачитанная программа начинается с
загрузчика, написанного на БЕЙСИКе. Программа, применяющая загрузку
без заголовков (с помощью процедуры 1366 или другой), должна быть на-
писана в машинном коде, как всякая процедура, обслуживающая магнито-
фон. Чаще всего эта программа помещается в одной из строк БЕЙСИКа,
например после инструкции REM или в области переменных БЕЙСИКа. После
считывания загрузчик на БЕЙСИКа запускается и выполняет инструкцию,
RANDOMIZE USR инициируя тем самым работу машинной программы.

Процедура LOAD_BYTES требует соответствующих входных параметров.
Они передаются в соответствующих регистрах микропроцессора. Так, в
регистре IX указываем адрес, по которому хотим прочесть блок данных,
а в регистре DE - длину этого блока. В аккумулятор помещаем 0, если
хотим считать заголовок и 255, если это - блок данных. Кроме того,
указатель переноса (CARRY) устанавливаем в 1, т.к. иначе процедура
1366 вместо LOAD выполнит VERIFY. Ниже дан пример процедуры, загружа-
ющей с ленты образ экрана без заголовка:
LD IX,16384 ;адрес считывания
LD ОЕ»6912 ;длина блока
LD А,255 ;блок, а не заголовок
SCF ' ;LOAD, а не VERIFY

CALL 1366 ;вызов L0AD8YTES
RET ;во$врат из п/п

Процедура 1366 в случав ошибки считывания не выводит сообщение
"ТАРЕ LOADING ERROR", но существует еще одна процедура загрузки, ко-
торая это делает. Она находится по адресу 20Б0 и выглядит так:
2050 CALL 1366 «-считывание блока данных

2053 RET С ;возврат, если не было ошибки

2054 RST 8 ;иначе RST 8 с сообщением

2055 DEFB 26 ;"ТАРЕ LOADING ERROR"

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

Иногда загрузчики не пользуются ни той, ни другой процедурой, а
заменяют их собственной. Однако, она часто является просто переделкой
.1366: например, блоки загружаются от больших адресов к меньшим или
загрузка идет с другой скоростью. Такую программу следует анализиро-
вать с помощью дизассемблера (например HONS), сравнивая ее фрагменты
с тем, что находится в ROM.

Сейчас мы объясним, как использовать процедуры из ROM для считы-
вания из БЕЙСИКа под любой адрес, а не в область, предназначенную для
него: сначала с помощью "CZYTACZ" прочитаем заголовок программы, ко-
торую мы хотим взломать, и запомним ее длину (т.е. длину всего блока
- программы вместе с переменными). Затем введем соответствующую прог-
рамму на ассемблере, которая прочитает БЕЙСИК-програиму по адресу,
который мы зададим (выше RAMT0P):
LD IX,addr
LD DE,len
LD A,255
SCF

JP 2050

Так же, как и при подмене заголовка, можем указать завышенное
значение длины программы (если не знаем истинного значения), но в

этой случае чтение завершится сообщением "ТАРЕ LOADING ERROR", Чтобы
не считывать АССЕМБЛЕР всякий раз для ввода вышеприведенной програм-
мы, создадим эту программу из БЕЙСИКа с помощью РОКЕ:
10 INPUT "АДРЕС ЧТЕНИЯ 7"; А
20 RANDOMIZE A: CLEAR А-1
30 LET А-РЕЕК 23670: LET В-РЕЕК 23671
40 LET ADR*256*B+A
50 INPUT "ДЛИНА ?"; С
60 RANDOMIZE С: LET С-РЕЕК 23570
70 LET D«PEEK 23671
80 FOR N-ADR TO ADR*11
90 READ X; POKE N,X: NEXT N
110 DATA 221,33,A,8Д7,С,0,62,255,125,2,8
120 RANDOMIZE USR ADR

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

В завершение стоит вспомнить еще об одной процедуре, размещенной
в ROM по адресу 1218. Это процедура SAVE_BYTES3 обратная LQAD_BYTES,
т.е. записывающая на ленту блок о заданными параметрами: перед ее вы-
зовом в регистре IX размещаем адрес, с которого начинается записывае-
мый блок, DE должен содержать длину этого блока, в аккумуляторе поме-
чаем, должен ли это быть заголовок (0) или же собственно блок (255).
Состояние указателя CARRY значения не имеет.




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

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



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

Похожие статьи:
Слово авторов - Надежда, что газета не умрет...
Железо - доработка INT'a Profi до Pentagon'воского.
Room Ten - Информация о дисковой версии игры.
Реклама - реклама и обьявления.
Наши новости - Последние новости от EXPERIENCE.

В этот день...   21 ноября