Тайники ZX Spectrum и как установить вечную жизнь 1994 г.

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


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

Что означает, что программа или блок закодированны ? Кодирование - это род
весьма простого шифра, делающего невозможным правильную работу программы.
Для ее запуска служит специальная декодирующая процедура, которая находится в
той же программе, а также, что самое важное, не закодированная. Так для чего же
служит кодирование? Это просто очередное затруднение доступа к тексту программы
после того как все предшествующие предохранители взломаны и программа считана
без самозапуска. В этом случае в памяти лежит "полуфабрикат**, который только после
переработки декодирующей процедурой становится программой. Кодирование может
быть основано на инверсии всех байтов в программе. Хорошим примером является
программа "ART STUDIO". Бе бейсиковая часть практически не защищена никак,но
главный блок программы ("STUDIO-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 дарование его с

26038 ЕЕСС XOR #СС «помощью SUB ДЬСА,

26040 77 LD (ШЛ ;XOR и запись

26041 23 ЮС HL {Следующий адрес

26042 В7 OR А {Проверка признака

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

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

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

26048 С9 RET {ному в стеке

26049 B2EDF1 {или 26049

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

Обратим внимание, какие инструкции осуществляют дешифрацию никакая из
них не теряет ни одного бита. Вычитание производится по модулю 25* i для двух
разных входных данных. Результаты тоже различны. RLCA заменяет зшпа л битов
7, 6, 3 и 2 на противоположные. Другими инструкциями, имеющими те же самые

свойства являются, например, ADO, INC, DEC, RRCA, NEG, CPL но не OR или AND.
Как раскодировать этот блок? Проще всего вводя в БЕЙСИКе:
РОКЕ 26027,0 (код инструкции NOP)

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

26283 67 LD НА ;В А уже находится

26284 6F LD Ц (значение 0

26285 Е5 PUSH HL (Запись его в стек
26292 ЗАА865 LD А, (26024) (и проверка
26295 FE21 CP #21 (содержимого ячеек

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

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

26301 В7 OR А (и если рно другое

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

26308 ЗААВ65 LD A,(26027) ((под адрес 0)

26311 FEE5 CP #E5 (Если все нормально

26313 СО RET NZ ;то снятие адреса 0

26314 El POP NZ (и нормальный

26315 С9 RET (выход

Этот фрагмент проверяет: наверняка ли декодирующая процедура запустила про-
грамму, и если нет, то спомощью RET NZ стирает память (т.к. в стеке записан адрес
0).

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

XOR #СС
RRCA
ADD 34

В "ART STUDIO" неизвестно для чего была помещена кодирующая программа. Она
находится под адресом 26003 и выглядит так:

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

26006 11476С LD DE.27719 (Адрес конца

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

26010 ЕЕСС XOR #СС (памяти, кодирование

26012 OF RRCA (его с помощью XOR

26013 С622 ADD 34 (RRCA, ADD И ЕГО

26015 77 LD (HL),A (Запись

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

26017 B7 OR А (Проверка окончания

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

26020 19 ADD HL.DE {возврат в БЕЙСИК

26021 20F2 JR NZ,26009 {

Как видно, она построена аналогично декодирующей процедуре. Если таковой
нет, то ее можно быстро и просто написать на основе декодирующей процедуры
(например ATIC, АТАС NIGHT SHADE, THE WORLD).

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

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

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

Префикс FDH или DDH относится ко всем регистрам Н, L, или HL, присутствую-
щим в команде, следовательно, в одной инструкции не возможно использование
ячейки адресованной как (HL), регистра HL, Н или L одновременно с НХ, HY, IX, JY
(в дальнейшем ограничимся регистром IX, но все это относится также и к регистру IY
), например;

66 LD H,(HL) DD66" LD HX,(IX+*)

75 LD (HL),L DD75** LD (IX+*),IX

65 LD H,D DD65 LD HL,IX

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

СВ13 RLE

DDCB0113 RL (IX+1),E

DDSB0116 RL (IX+1)

DD5E01 LD E,(IX+1)

В конце рассмотрения инструкции этого типа следует вспомнить, что команд ЕХ
DE, DC или EX DE, IY нет. Префиксирование команды EX DE,HL не дает никаких
результатов. Также префиксирование команд, коды которых начинаются с EDH, а
также тех, в которых не присутствует ни один из регистров Н, L или пары HL
(например LD В Л, RRCA и т. д.).

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

СВ36 S U (HL)

DDCB**36 SLI (IX+*)

DDCB**57C SU (1Х+*)Л

Временами некоторые проблемы вызывают построение флажкового регистра, осо-
бенно тоща, когда он используется достаточно нетипично, например:
PUSH AF
POP ВС
RL С
JP NC,...
Его вид представлен на рис. 1.

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

XOR А {Запись значения О

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

{Указатели будут: F5-0; F3-1
Последняя (кто поручится, что их больше нет ?) тайна Z80 это регистр обновления
памяти Р. А точнее то, что когда после очередного машинного цикла микропроцессора
инкрементируется значение этого регистра, то его старший бит остается неизменым,
следовательно может быть использован для хранения любой, естественно однобито-
вой, информации. Важно также то, что инструкция LD А, Р с помощью которой может
быть получена эта информация, устанавливает также указатель S и, следовательно
не требуется дополнительная инструкция, проверяющая значение этого бита.

В конце несколько коротких, но часто приемлемых мер защиты. Их ликвидация
основывается обычно на действиях обратным защитным. Например, переменная
DFSZ (23659) определяет число строк в нижней части экрана, требуемое для вывода
сообщения об ошибке или для ввода данных. Во время работы программы это значение
равно двум, но достаточно занести туда 0, чтобы программа зависла при попытке

прерывания (т.к. выводится сообщение для которого нет места). Если в программе
находится инструкция INPUT или CLS, то она имеет подобный результат.

Распространенным способом защиты является также изменение значений пере-
менной BORDCR (23624), которая определяет цвет рамки и атрибутов нижней части
экрана. Значение отдельных битов следующие:
7 бит -FLASH

6 бит -BRIGHT

5,4.3 биты -BORDER
2,1,0 биты -INK

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

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

Известным способом защиты является также занесение значения больше 9999 в
ячейки памяти, обозначающие номер строки БЕЙСИКа (первый байт - старший).
Если он размещается в границах 10000 -16383, а на листинге это выглядит, например
0000 (вместо 10000) и строки невозмжно скорректировать (EDIT), если же превыша-
ет 16384 - дальнейшая часть программы считается не существующей. Можно также
встретить защиту основывающуюся на занесении минимальных значений (то есть 1)
в переменные REPDEL (23561) и REPPER (23562), что затрудняет работу с компью-
тером, но для ее ликвидации требуется лишь быстрая реакция (запиши с помощью
РОКЕ нормальные значения: 35 и 5).

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

СЧАСТЛИВОЙ РАЗБОРКИ ПРОГРАММ Ш




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Рассказ - Ну, юзер, погоди!
Ликбез - Ассемблер взгляд издалека: Логические операции, Операции AND, OR,XOR,NOT; мнемоники. Результаты действия команд.
Обзор новинок - Putup (demo).

В этот день...   26 мая