3. ЗАЩИТА ПРОГРАММ НА БЕЙСИКЕ
Прочитанная пограмма, как правило, не должна выглядеть нормально. Например,
в программе есть строка с номером 0 или строки упорядочены по убыванию номеров.
Нельзя вызвать EDIT ни для какой строки, видно подозрительную инструкцию
RANDOMIZE USR 0 или просто ничего не видно, т.к. программа не позволяет листать
себя. Если в программе, куда ты вламываешься, ты увидел что-то необычное, то лучше
просматривать ее друтм способом, несколько отличающимся от обычного - не с
помощью UST, а непосредственно, используя функцию РЕЕК, однако, сначала мы
должны узнать каким образом размещен в памяти текст программы на БЕЙСИКе.
Программа складывается из последовательных строк и так и хранится в памяти.
Отдельная строчка программы выглядит так:
Она занимает не менее 5 (а точнее 6, т.к. текст пустым быть не может) байт. Два
первых означают ее номер. Но он записан наоборот, от всех обычных 2- байтовах
чисел, хранимых в памяти (MSB - старший байт, LST - младший байт).
Следующие 2 байта -это длина строки, т.е. число символов содержащихся в сроке
вместе с завершающим ее знаком "ENTER" (#0D). За этими байтами находится текст
строки, заканчиваемый "ENTER".
Если введем, к примеру, такую строку:
10 REM BASIC
и запишем ее, нажимая клавишу "ENTER", то она будет записана в память как
последовательность байт:
Параметр "Длина строки" касается только ее текста, следовательно хотя строка
занимает в памяти 11 байт, этот параметр указыват только на 7 байт: 6 байт текста и
1 байт "ENTER", заканчивающий строку*
Тебе, наверное, уже понятно на чем основан часто применяемый трюк со строкой,
имеющей нулевой номер. Достаточно в первые 2 байта занести число 0 (с помощью
РОКЕ), чтобы эта строка стала нулевой строкой. Если мы хотим изменить номер
первой строки в программе (а к интерфейсу никакая быстрая память не подключена,
т. к. в этом случае изменяется адрес начала БЕЙСИКа), то достаточно написать:
РОКЕ 23755, X: 23756, Y
и строка получит номер 256*X+Y. Не зависимо от его значения строка останется в
памяти там где была. Если введем:
10 REM НОМЕР СТРОКИ 10
20 REM НОМЕР СТРОКИ 20
РОКЕ 23755,0:РОКЕ 23756,30
то первой строке в программе будет присвоен номер 30, но она останется в памяти
как первая, а на экране мы получим след:
30 REM НОМЕР СТРОКИ 10
20 REM НОМЕР СТРОКИ 20
следовательно, чтобы начать разблокировать программу, в которой имеются нуле-
вые строки или строки, упорядоченные по убыванию номеров, следует найти адрес
каждой строки и в их поле "НОМЕР СТРОКИ" последовательно размещать к примеру:
10,20... В памяти строки располагаются одна за другой, следовательно с обнаруже-
нием их начал ты не будешь иметь трудностей. Если X указывает адрес какой-нибудь
программной строки, то следующий адрес равен:
Х+РЕЕК(Х+2)+256*РЕЕК(Х+3)+4
т.е. к адресу строки добавляется длина ее текста, увеличеная на 4 байта, т.к. именно
столько занимают параметры "НОМЕР СТРОКИ" и "Д ЛИНА СРОКИ".
Такой способ нахождения не действует, к сожалению, когда применяется другой
способ защиты - фальшивая длина сроки. Он основан на том, что в поле "ДЛИНА
СТРОКИ" вместо настоящего значения дается Очень большое число - порядка 43-65
тысяч. Этот способ применяется очень часто, т. к. обычно делает невозможным счи-
тывание программы с помощью MERGE (т.е. так, чтобы не было самостарта). Дела-
ется это потому, что MERGE загружает программу в область WORKSPACE, а затем
интерпретатор анализирует всю считанную программу строка за строкой: последова-
тельно проверяет номер каждой из них, а затем размещает ее в соответствующем месте
области, предназначенной для текста программы на БЕЙСИКе. Для этой строки
необходимо там подготовить соответствующее количество свободных байт, "РАЗДВИ-
ГАЯ" уже существующий текст программы. Если в поле "ДЛИНА СТРОКИ" стоит
очень большое число, то интерпретатор старается выделить именно столько байтов
пространства в области текстов программы, что завершится сообщением "OUT OF
MEMORY** или просто зависанием системы. Чтобы прочесть такую программу не
вызывая ее самозапуск, следует применить соответствующую отмычку, например,
такую как представленная в разделе 2 программа NLOAD/MERGE**. Дополнительным
эффектом от применения фальшивой длины является невозможность в корректировке
такой строки путем занесения в ее поле. Это требует слишком большого количества
памяти, следовательно кончается только предупредительным звонком.
Если программа защищена таким способом, то адреса очередных строк приходится
искать вручную или догадываться, где находятся, помня, что каждая строка заканчи-
вается знаком ENTER (но не каждое число 13 означает ENTER). Чтобы просмотреть
программу на БЕЙСИКе, введи такую строку:
FOR N-23755 ТО PEEK 23627+256*РЕЕК 23628:
PRINT N?" "(РЕЕК N; CHR$ РЕЕК N AND РЕЕК31:
NEXTN
Она последовательно высветит: адрес, содержимое байта с этим адресом, а также
символ, имеющий этот код, если это только не управляющий символ (т. е. с кодом
0...31).
После смены нумерации строк и изменения их длины, следующим способом защи-
ты программ являются управляющие символы, не позволяющие последовательно
просматривать программу, хотя и не только это.
Вернемся к первому примеру (строка" 10 REM BASIC**). Текст строки складывается
из 7 символов - ключевого слова REM (все ключевые слова - инструкции и функции,
а также знаки <-, >ио имееют однобайтовые коды из диапазона 165... 255. Если
ты не знаешь какие, то введи:
FOR N-165 ТО 255 :PRINT N, CHR$ N: NEXT N
и ознакомься), а также пяти литер и символа "ENTER**. Так бывает всегда, если в
строке находится инструкция REM - все знаки, введенные с клавиатуры после этой
инструкции, будут размещены в памяти без малейших изменений. Иначе выглядит
ситуация, когда в строке находятся другие инструкции, требующие числовых пара-
метров (а обычно тай и бывает). Введем, к примеру, строку:
10 PLOT 10,9
и посмотрим, каким образом она запишется в память (лучше вводя переменную
выше строки №23755 то...). Выглядит она так, как показана на рисунке 3.
Как видно, текст был модифицирован - после последней цифры каждого числа,
выступающего в тексте строки как параметр, интерпретатор сделал б байтов простран-
ства и поместил там символ с кодом 14, а также 5. байтов, в которых записано значение
этого числа, но способом, понятным интерпретатору. Это убыстряет, в определенной
мере, выполнение прбграммы на БЕЙСИКе, т. к. во время выполнения не должен
каждый раз переводить числа из алфавитно-цифрового представления (последова-
тельности цифр) на пяти байтовое представление, пригодное для вычислений. Гото-
вое значение выбирается из памяти из-за управляющего символа CHR$ 14. Эта
странная запись дает большие возможности в БЕЙСИКе в деле затруднения доступа
к программам. Во многих программах загрузчиков' (LOADER) присутствует такая
строка:
О RANDOMIZE USR 0: REM ~
На первый взгляд эта программа после запуска должна затереть всю память, но
так, однако, не происходит. После более внимательного просмотра (с помощью РЕЕК
- строка FOR N-23755...) оказывается, после USR 0 и символа CHR$ 14 совсем нет
пяти нулей (именно так выглядит в пятибайтовой записи число 0). Если это целое
число, то в пятибайтовой записи оно выглядит:
Байт 1 -О
Байт2 -0 (для +) и255 (для-)
Байт 3 и 4 - последовательно младший и старший.
(или дополнение до 2 для -)
Байт 5 -О
К примеру 0,0,218,92,0, это равнозначно числу 23770. Функция USR не осуще-
ствляется, и тогда идет переход по адресу 0, а именно по 23770, а это как раз адрес
байта, находящегося сразу после инструкции REM в нашем примере. Там обычно
находится программа - загрузчик, написанная на машинном языке.
Следующим управляющим символом, часто применяемым для защиты, является
CHR$ 8 -"BACKSPASE" или пробел назад. Высвечивание этого символа вызывает
сдвиг позиции ввода на одну позицию назад влево, следовательно, с его помощью
можно закрывать некоторые позиции на листинге, печатая на их месте другой текст,
если, например, в памяти находятся знаки:
LET A-USR 0: REM ««««««««
LOAD ...
( < обозначает CHR$ 8 ), то инструкция LOAD "" и последующий текст закроет
инструкцию LET A-USR 0:. Хотя на листинге теперь видна только инструкция LOAD
"*:, но дальнейшая часть программы загружается не ею, а машинной программой,
запускаемой инструкцией USR 0 ( что очевидно, не должно обозначать переход к
адресу 0). Такая защита, например, применяется в загрузчике программы BETA
BASIC 1.0.