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

Глава 7 - декодирование закодированных блоков типа "bytes".


7. ДЕКОДИРОВАНИЕ ЗАКОДИРОВАННЫХ БЛОКОВ ТИПА "BYTES".

Что означает, что программа или блок закодированы? Кодирование -
это род весьма простого шифра, делающего невозможным правильную рабо-
ту программы. Для ее запуска служит специальная декодирующая процеду-
ра, которая находится в этой же программе, а также (что самое важное)
не закодирована. Так для чего же служит кодирование? Это просто оче-
редное затруднение доступа к тексту программы после того, как все
предшествующие предохранители взломаны и программа считана без запус-
ка. В этом случае в памяти лежит "полуфабрикат", который только после
переработки декодирующей процедурой становится программой. Кодирова-
ние может быть основано, например, на инверсии всех байтов в програм-
ме. Хорошим примером является программа "ART STUDIO", fie БЕЙСИКовская
часть практически никак не защищена, но главный блок программы
("STUDI0-MC" CODE 26000,30672) частично закодирована. Что сделать,
чтобы раскодировать его? Просто найти адрес, с которого этот блок за-
пускается. В случае "ART STUDIO" этот адрес - 26000. Там находится
инструкция JP 26024, которая осуществляет переход к декодирующей про-
цедуре. Вот ее текст:

26024 21С165 LD HL,26049; Запись адреса

26027 Е5 PUSH HL ; 26049 в стек.

26028 21С165 LD HL,26049; Адрес начала

26031 11476С LD DE,27719; Адрес конца

26034 7Е LD A,(HL) ; Выбор байта из

26035 D622 SUB 34 ; памяти, перекоди-

26037 07 RLCA ; рование его с . j-

26038 ЕЕСС X0R #СС ; мощью SUB, RLCA,

26040 77 LD (HL),A ; X0R и запись.

26041 23 INC HL ; Следующий адрес

26042 B7 OR A ; Проверка признака

26043 ED52 SBC HL,DE ; конца, возврат в

26045 19 ADD HL,DE ; цикл или выход no

26046 20F2 JP NZ,26034; адресу, записан-

26048 C9 RET ; HQMy в стеке или

26049 B2EDF1 ; по 26049

Сначала процедура помещает в стек адрес 26049, после чего в ре-
гистр,HL заново загружается 26049 (начало закодированного блока), а в

DE -27719 (адрес последнего закодированного байта). Затем в цикле
последовательно декодируются байты .- инструкции SUB 34, RLCA и X0R
#СС являются ключем, с помощью которого расшифровывается эта часть
программы. Наконец, проверяется условие достижения адреса 27719, как
последнегб декодируемого. Выполняется инструкция RET, но последним
записанным в стек адресом является не адрес возврата в БЕЙСИК, а за-
писанный в начале процедуры с помощью PUSH HL адрес 26049 (или адрес
только что раскодированного блока). Следовательно, происходит его за-
пуск.

Обратим внимание, какие инструкции осуществляют дешифрацию: ника-
кая из них не теряет ни одного бита. Вычитание осуществляется по мо-
дулю 256, и для для двух разных входных данных результаты тоже раз-
личны. RLCA заменяет значения битов 7, 6, 3 и 2 на противоположные.
Другими инструкциями, имеющими те же самые свойства, являются, напри-
мер, ADD, INC, DEC, RRCA, NEG, CPL, но не OR или AND. Как раскодиро-
вать этот блок? Проще всего ввести в БЕЙСИКе

РОКЕ 26027,0 (код инструкции NOP)
ликвидируя тем самым инструкцию PUSH HL (RET в конце программы приве-
дет в БЕЙСИК), и выполнить RANDOMIZE USR 26000. Стоит, однако, пом-
нить о том, что декодирующая программа может провериться другим фраг-
ментом программы. В "ART STUDIO" так и есть. Вот дальнейшая часть
программы:

26289 67 LD Н,А ;в А уже находится

26290 6F LD L,А ;значение 0

26291 Е5 PUSH HL ;запись его в стек

26292 ЗАА865 LD А,(26024) ;и проверка содер-
26295 FE21 CP #21 ;жимого ячеек

26297 СО RET NZ ;с адресами

26298 2АА965 LD HL,(26025);26024..26027

26301 87 OR А ;и если оно другое,

26302 11С165 LD DE,26049 ;то стирание памяти
26305 ED52 SBC HL,DE ' ;с помощью RET NZ

26307 СО RET NZ ;(под адрес 0)

26308 ЗААВ65 LD А,(26027) ;если все нормально
26311 FEE5 CP #Е5 ;то снятие адреса 0

26313 СО RET NZ ;и нормальный

26314 El POP HL ;выход

26315 С9 RET ;

Этот фрагмент программы проверяет, наверняка ли декодирующая про-
цедура запустила всю программу, и если нет, то с помощью RET NZ сти-
рает память (т к. в стеке записан 0). Что делать в этом случае? Можно
ликвидирован, и эти меры защиты, но в некоторых программах эта мера
не поможет. Тогда остается другой выход: снова закодировать програм-
му, т.е. сделать обратное действие. В наиГем случае следовало бы вы-
полнить

X0R #СС
RRCA

ADD 34

В "ART STUDIO" неизвестно для чего была помещена кодирующая прог-
рамма. Она находится по адресу 26003 и выглядит следующим образом:
26003 21С165 LD HL,26049 ;адрес начала
26006 11476С LD DE,27719 ;адрес конца
26009 7Е LD A,(HL) ;выборка байта из

26010 EECC X0R #СС ;памяти, кодирование

28012 OF RRCA ;его с помощью X0R,

26013 С622 ADD 34 ;RRCA, ADD и его

26015 77 LD (HI),А запись

26016 23 INC HL ;следующий адрес

26017 87 OR А ;проверка окончания

26018 ED52 SBC HL, DE ;переход в цикл или

26020 19 ADD HL,DE ;воиврат в БЕЙСИК

26021 20F2 JR N2,26009 ;

26022 С9 RET

Как видно, она построена аналогично декодирующей процедуре. Если
таковой нет, то ее можно просто и быстро написать на основе декодиру-
ющей процедуры,

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

Наиболее часто встречаемыми неопубликованными инструкциями явля-
ются команды, оперирующие на половинках индексных регистров IX и IY в
группе команд, котбрым не предшествует никакой иной префикс(т.е. СВН
или EDH). Основываются они на префиксации кодом DDH или ГОН команды,
касающейся регистра Н или L. В этом случае вместо этого регистра бе-
рется соответствующая половина индексного регистра. Через НХ обозна-
чается старшая половина регистра IX, через LX - младшая. Аналогично
HY и LY.

Вот примеры:

Это верно для всех команд пересылки однобайтовых данных между ре-
гистрами восьмибайтовых операций AND, OR, XOR, ADD, ADC, SUB, ВС и
CP, выполняемых в аккумуляторе.

Префикс FDH или DDH относится ко всем регистрам Н, L или HL, при-
сутвующим в команде. Следовательно, в одной инструкции невозможно ис-
пользование ячейки, адресованной как (HL), регистра HL, Н или L од-
новременно с НХ, HY, LX, LY, ( в дальнейшем ограничимся регистром IX,
но все это относится также к регистру IY), например:
66 ID Н Д HL) DD66** LD НХД1Х+*)
75 LD (HL),L DD75** LD (IX+*),IX
65 LD H.L DD65 LDHX,IX

Несколько иначе представляется ротация ячейки, адресуемой индекс-
ным «регистром, т.е. инструкций, начинающихся кодом DDC8. Инструкция
типа RR (IX+*) и ии подобные подробно описаны во всех доступных мате-
риалах о микропроцессоре Z80, но мало кто знает об инструкциях типа
RR (1Х+*),% и им подобным, где % обозначает любой регистр микропро-
цессора. Они основываются на префиксировании кодом DDH или FDH инс-
трукции типа RR %. Так же обстоит дело с инструкциями SET N.(IX+*),%,
а также RES N,(IX+*),% (но для BIT уже нет),. Выполнение такой инс-
трукции основано на выполнении нормальной команды RR (IX**) (или по-
добной), SET N,(IX+*) или RES N,(IX+*h а затем пересылки результата
как в ячейку (IX+*), так и соответствующий внутренний регистр микроп-
роцессора. Например;

С813 Rl Е

00СВ0113 RL (1Х+1),Е
вызывает сдвиг ячейки с адресом IX+1 влево на 1 бит и пересылку ре-
зультата в регистр Е, что обычным способом следовало бы сделать так:
00С80116 RL {1X^1)
005Е01 L0 ЕЛ1Х+1)
В конце рассмотрения инструкций этого типа следует вспомнить, что
команд ЕХ ОЕ,IX или EX 0E,IY нет. Префиксование команды EX 0E.HL не
дает никаких результатов. Также * префиксование команд, коды которых
начинаются с EDH, а также тех, в которых не присутствует ни один из
регистров H,L или пары HL (например, 10 B,N, RRCA и i.д.).

Очередной любопытной командой является SlI (SHIFT LEFT AND
INCREMENT), выполнение которой аналогично SLA с той разницей, что са-
мый младший бит устанавливается в 1, Признаки устанавливаются иден-
тично SLA и другим сдвигам:
СВ37 SLI А

СВЗб SLI (HL)

DDCB**36 SLI (IX+*)
DDCB**57 SLI (IX+*),A
Временами некоторые проблемы вызывает построение флажкового ре-
гистра, особенно тогда, когда он используется достаточно нетипично,
например:

PUSH AF
POP ВС

RL С

JP NC,..*

Его вид представлен на рисунке:

Дополнительной особенностью регистра F является то, что биты 3 и
5 (обозначенные как F3 и F5) точно отражают состояние восьмибитовой
арифметической или логической операции, а также команд IN %,(С) и IN
F,(C). Например, после выполнения:

X0R А ;запись значения О

ADD А,15 ,-результат - 00001111

указатели будут: F5 = 0; F3 * 1

Последняя (кто поручится, что их больше нет?) тайна 280 - это ре-
гистр обновления памяти R. А точнее то, что когда после очередного
машинного цикла микропроцессора инкрекентируегея значение этого ре-
гистра, то его старший бит остается неизиенным, следовательно, он мо-
жет быть использован для хранения любой, естественно однобитовой ин-
формации. Важно также то, что инструкция LD A, R, с помощью которой
может быть получена эта информация, устанавливает также указатель S
и, следовательно, не требуется дополнительная инструкция, проверяющая
значение этого бита.

В конце - несколько коротких, но часто применяемых мер защиты. Их
ликвидация основывается обычно на действиях, обратным защитным. Чаще
всего с этой точки зрения эксплуатируются системные переменные. Нап-
ример, переменная DFSZ (23659) определяет число строк в нижней части
экрана» требуемую для вывода сообщения об оиибке или ввода данных. Во
вр^мя работы программы это значение обычно равно 2, но достаточно за-
нести туда 0, чтобы программа зависла при попытке прерывания (т.к.
выводится сообщение, для которого нет места). Если в программе нахо-
дится инструкция INPUT или CLS, то она имеет подобный результат.

Распространенным способом защиты является также изменение значе-
ния переменной B0RDCR (23624), которая определяет цвет рамки и атри-
бутов нижней части экрана. Значение отдельных битов следующее:
7 бит - FLASH
6 бит - BRIGHT
5..3 биты - PAPER
2..0 биты - INK

Способ защиты основывается на том, что цвет чернил - тот же са-
мый, что и у рамки. Следовательно, при остановке программы можно по-
думать, что она зависла (не видно сообщения). Разблокировать защиту
можноf вписав BORDER 0 (или другой цвет).

Очередным простым способом защиты является изменение значения пе-
ременной ERRSP (23613, 23614) или дна машинного стека (эта переменная
указывает на дно стека), где обычно находится адрес процедуры, обра-
батывающей ошибку БЕЙСИКа (вызываемой с помощью RST 8). Уменьшение
значения ERRSP на 2 вызывает защиту программы от "BREAK" и любой дру-
гой ошибки - программа заново запускается с места, в котором произош-
ла ошибка. Смена содержимого дна машинного стека или другая замена
содержимого ERRSP может вызвать зависание или даже рестарт компьюте-
ра .

Известным способом защиты является также занесение значений боль-
ших 9999 в ячейки памяти, обозначающие номер строки БЕЙСИКа (первый
байт - старший). Если он размещается в границах 100С..16383, то на
листинге это выглядит, напримерг ООО (вместо 1000) и строки эти не-
возможно скорректировать (EDIT). Если же номер превышает 16384, то
дальнейшая часть программы считается несуществующей,

Можно также встретить защиту, основанную на занесении минимальных
значений (т.е. 1) в переменные REPDEL (23561) и REPPER (23562), что
затрудняет работу с компьютером. Для ее ликвидации требуется лишь
быстрая реакция (запишите с помощью РОКЕ нормальные значения: 35 и
5).

Стоит еще вспомнить о переменной NMIAQD, которая не используется
из-за ошибки в ROM. Она должна была содержать адрес подпрограммы об-
работки NMI-прерывания. Ошибка в том, что микропроцессор переходит
туда лишь тогда, когда он равен 0. Если, одчзко, добавить к SPECTRUM
соответствующую приставку с памятью EPR0M, то путь к задержке любой
программы будет открыт.




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

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



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

Похожие статьи:
От авторов - Virt group и газета ZX-News.
News - I wish all the Spectrum people to make even more for the sake of our beloved platform!
Я не слабоумный - задача была хитро придумана, но я ее одолел. Готово!
Вступление - От авторов.
Реклама - Реклама и объявления ...

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