Работа с ZX-Spectrum 1993 г.

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


ГЛАВА 5

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

Все игры имеют очень хорошо защищенную программу, написанную на
BASIC'e, так как это важнейший (с точки зрения действенности защиты) эле-
мент всей протаммы - ведь с BASIC'a начинается считывание всей програм-
мы. Если BAblC-загрузчик защищен слабо, то взлом всей программы
значительно облегчен, примером этого являются загрузчики фирмы
ULTIMATE, представленные в предыдущем разделе. Одним из способов
снятия защиты загрузчиков является считывание их с помощью программы
«LOAD/MERGE» (см. главу 2). Однако иногда лучше поместить этот загрузчик
не в памяти, предназначенной для BASIC'a, а выше RAMTOP, чтобы можно
было спокойно просматривать его, не опасаясь возможности случайных
изменений в нем.

Для этого имеется очень действенный метод - считывание программы
на BASIC'e как блока машинного кода под удобный для нас адрес. Чтобы это-
го добиться требуется знать длину программы, которую мы хотим считать
(можешь использовать процедуру «CZYTACZ» из главы 2), хотя можно
обойтись и без длины. Кроме того, требуется немного свободного места на
магнитной ленте. Этот способ основывается на обмане инструкции LOAD
путем подмены заголовков.

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

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

CLEAR 29999: LOAD "" CODE

или

CLEAR 29999: LOAD "" CODE 30000

и считываем заголовок. Сразу после его считывания, мы нажимаем
STOP в магнитофоне, заменяем кассету и вновь нажимаем PUSK (все. это
время компьютер ждал блока данных). Теперь считывается программа на
Basic'e. но под адрес 30000 - выше RAMTOP. Если мы задали в заголовке за-
вышенную длину программы, то считывание заканчивается сообщением
«ТАРЕ LOADING ERROR», но это не мешает - теперь уже любым способом
можно смотреть считанную программу, даже набирая с этой целью програм-
му на Basic е

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

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

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

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

LD IX,16384; адрес считывания

LD DE,6912 длина блока

LD А,155; блок данных

SJF; установка CARRY

CALL 1366; вызов LOAD-BYTES

RET; выход из подпрограммы

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

2050 CALL 1366; считывание блока данных

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

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

2055 DEFB 26; «ТАРЕ LOADING ERROR»

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

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

Сейчас мы объясним, как использовать процедуры из ROM для считы-
вания BASiC'a под любой адрес, а не в область, предназначенную для него.
Сначала с помощью «CZYTACZ» прочитаем заголовок программы, которую
мы хотим вскрыть, и запомним её длину (т.е. длину всего блока - программу
вместе с переменными). Затем вводим соответствующую программу на
Ассемблере, которая прочтет Basic по адресу, который мы установим (выше
RAMTOP):

LD IX, адрес
LD DE, длина
LD А,255
SCF

JP 2050

Так же, как и при подмене заголовка, если мы не знаем длины програм-
мы, то можем задать завышенное значение, но тогда чтение завершится со-
общением «ТАРЕ LOADING ERROR». Но считывание Ассемблера каждый
раз, чтобы ввести программу, приведенную выше, может вызвать раздра-
жение, следовательно, лучше создавать эту программу с уровня Basic'a с
помощью РОКЕ:

10 INPUT "адрес чтения BASIC ?";А

20 RANDOMIZE A: CLEAR А-1

30 LET А=РЕЕК 23670: LET В=РЕЕК 23671

40 LET ADRse256*B+A

50 INPUT "длина BASIC ?м; С

60 RANDOMIZE С: LET С=РЕЕК 23670

70 LET D=PEEK 23671

80 FOR N=ADR TO ADR+11

90 READ X: POKE N,X

100 NEXT N

110 DATA 221,33,А,В* 17,C,D,62,255,195,2,8
120 RANDOMIZE USR ADR

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

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

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




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
заключение - авторы и т.д.
Бук - рассказ "Интим-полигон".
Rest in Paint - Beard^AMD приобрел на днях автомобиль.
Necronomicon - Следующий раздел "НЕКРОНОМИКОНА" наиболее опасный из всех Книг
AMIGA-новости - Что будет с Амигой?

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