Техника защиты компакт-дисков от копирования

Диск с нулевым треком


Задумывались ли вы, почему нумерация треков лазерных дисков начинается с единицы, а не с нуля? Ведь говорят, чтобы отличить программиста от простого смертного достаточно дать ему команду "рассчитайсь!". Нормальный человек скажет "первый" (если он действительно первый) и будет по-своему прав. Программист же сначала уточнит в какой системе исчисления вести расчет (в двоичной, восьмеричной, шестнадцатеричной…) и затем, сделав шаг вперед, гордо скажет "нулевой". "Так ведь лазерные диски изначально разрабатывались для пользователей!"—– ответите вы, —– "а пользователи более привычны к натуральной, а не позиционной системе исчисления и потому первый трек должен быть именно первым, но никак не нулевым".

И все же, несмотря на всю убедительность своих доводов, вы будете не правы. Отсчет треков всякого диска начинается не с единицы, ано с нуля. Да, нулевой номер зарезервирован за служебным треком (вводной областью диска) и его содержимое недоступно на интерфейсном уровне, но это ничего не меняет! Поле TNO (Track Number) Q-подканала диска области Lead-inLead-In области диска равно нулю, следовательно, с точки зрения привода всякий диск начинается с трека номер ноль. Электронная начинка привода читает и адресует нулевой трек точно так же, как и любой другой трек диска, сохраняя тем самым прозрачность и упорядоченность принятой системы нумерации. С точки зрения системных программистов, разрабатывающих микропрограммные прошивки, отсчет треков всегда начинается с нуля. С точки же зрения пользователей привода —– с единицы. Одним словом, и "волки сыты и овцы целы!"

Атрибуты нулевого трека отсутствуют в TOC, поскольку этот трек как раз и служит для хранения TOC. Давайте задумаемся, что произойдет, если одному из point'ов указателей подлинного или фиктивного трека мы присвоим значение ноль, то есть, попросту говоря, создадим еще один нулевой трек в пользовательской области диска?

Если помимо внесения подложных данных в TOC, мы еще и скорректируем содержимое Q-канала подкода, забив заполнив поле TNO нулями, то с точки зрения привода такой трек будет неотличим от вводной области диска и попытка его посекторного чтения будет обречена на провал (хотя некоторые приводы и не такое читают).
Субканальные данные нулевого трека теоретически должны быть доступны для чтения командами SEEK или /READ SUBCHANNELL, но никаких гарантий на счет этого у нас нет, поскольку наличие двух подряд идущих областей Lead-inLead-In областей сильно нервирует привод, и его реакция становится совершенно непредсказуемой. Отказ от восстановления субканальных данных мало что меняет. Одно лишь наличие нулевого point'a указателя в TOC'е —– событие вполне неординарное и взаимно противоречивое.

Большинство приводов просто "свихнутся" и откажутся обрабатывать такой диск, совершенно непредсказуемым образом осуществляя чтение его оглавления. В частности, NEC при выполнении команды READ TOC возвращает ошибку, ASUS воспринимает нулевой трек как индикатор завершения TOC'а, а TEAC, столкнувшись с нулевым треком, начинает очень сильно "нервничать" и вместо атрибутов всех последующих треков "выплевывает" содержимое своих внутренних буферов вместе с мусором, оставшимся от TOC'а предыдущего диска. Короче говоря, нулевой трек делает лазерный диск практически полностью нечитабемльным.

На этом, собственно, можно было бы и остановиться (кому нужна жутко конфликтная защита, работающая исключительно в лабораторных условиях и крайне нежизнеспособная на практике?!) если бы не одно "НО". Стремительное падение цены на оптические носители позволяет использовать лазерный диск не только для хранения полезной информации, но и в качестве своеобразного ключа.

Весь фокус в том, что наличие нулевого трека на диске никак не препятствует чтению субканальных данных спиральной дорожки, но подавляющее большинство копировщиков (включая Alcohol 120% Алкоголь и Clone CDCloneCD) скорее "зависнут", чем скопируют такой диск! Таким образом, алгоритм работы защитного механизма сводится к "ручному" чтению TOC'а командами SEEK или /READ SUBCHANNEL с последующей проверкой его содержимого на предмет наличия нулевого трека.

И хотя ключевой диск не может содержать никаких других данных кроме собственно самого проверяемого TOC'а —– это ли беда? В каком-то смысле это даже достоинство.


Пусть на одном лазерном диске, никак не защищенном от копирования, содержится демонстрационная версия программы, свободно доступная и для скачивания через Интернет. Чтобы она превратилась в полноценную полнофункциональную версию, пользователь должен вставить в привод ключевой диск, полученный от регионального дилера или переданный непосредственно самим разработчиком по почте (собственно, не обязательно постоянно держать ключевой диск в приводе, защита может запомнить флаг регистрации и в реестре, запрашивая ключевой диск лишь изредка —– на тот случай если пользователь захочет одолжить его кому ни будь). Согласитесь, это гораздо надежнее ключевого файла или регистрационного номера, которым ничего не стоит поделиться с другом или выложить в Интернет, а, учитывая что cубканальные данные диска могут хранить не только ключ, но и исполняемый (интерпретируемый) код, обеспечивающий полнофункциональность зарегистрированной программы, становится ясно, что если у хакера нет ни одной полностью работоспособной копии защищенного приложения, взломать его за разумное время будет просто нереально. Но довольно слов, перейдем к делу, попытавшись перво-наперво создать образ защищенного диска с нулевым треком внутри. Как мы сейчас и увидим, это оказывается это не так-то просто сделать!



Если просто обнулить указатель (point) первого трека, то Clone CDCloneCD наотрез откажется открывать такой образ, ссылаясь на ошибку анализа. На самом деле этих ошибок по меньшей мере две. Первая —– полная неосведомленность Clone CDCloneCD о потенциальной возможности существования нулевых треков, коих он в упор не видит. Вторая —– непростительный оптимизм, закладывающийся на тот факт, что каждая сессия должна содержать в себе по меньшей мере один трек (что в действительности вовсе не факт, а лишь допущение).

Alcohol 120% Алкоголик воспринимает сессию с единственным нулевым треком внутри более благодушно, корректно отображая его номер (см. листинг 6.40 ниже), однако, при попытке записи такого образа на диск, выпрыгивает появляется сообщение об ошибке "access violation" (нарушение доступа) и копировщик "наглухо повисает", даже не удосужившись аварийно завершить свою работу (см.


рис. 6.210x104). Вызов "Диспетчера программ" с последующим " умерщвлением разбушевавшегося" процесса не решает проблемы, т. к. лоток диска остается заблокированным и приходится прибегать к помощи утилиты CD.lock.exe для уменьшения счетчика блокировок на единицу.

Листинг 6.40. Alcohol 120% открывает образ защищенного диска вполне успешно, честно отображая нулевой номер первого трека, правда некорректно определяет его длину

Тип:          Файл-образ CloneCD

Путь:        L:\CD-hack\

Имя:          IMAGE.CCD

                   IMAGE.img

                   IMAGE.sub

Размер:     8.81 MB

Сессий:            2

Треков:            2

Сессия 01:

  Трек 00: Mode 1, Длина: 000000(0 Byte), Адрес: 000000

Сессия 02:

  Трек 01: Mode 1, Длина: 000000(0 Byte), Адрес: 013458

Листинг 32 Алкоголик открывает образ защищенного диска вполне успешно, честно отображая нулевой номер первого трека, правда некорректно определяет его длину.



Рис. 6.21. унок 16 0x104 Реакция Alcohol 120% Алкоголика на попытку записи образа диска с единственным нулевым треком внутри первой сессии

Постойте, но ведь это же… Это же настоящая золотая жила! Диск с единственным нулевым треком внутри первой сессии не то, что не копируется, он даже и не "прожигается"! Даже если хакер каким-то неизвестным науке способом снимет с защищенного диска правильный дамп, ему будет нечем этот дамп записать!!! Правда и разработчику защищаемого приложения ключевой диск нечем записать тоже… ну, разве что отважиться на разработку собственной программы "прожига". Естественно, изготовить штампованные CD с нулевым треков вообще не проблема, но этот путь доступен далеко не всем (индивидуальным программистам он недоступен точно).

Компромиссным вариантомв защиты становится добавление в искажаемую сессию хотя бы единственного ненулевого трека. Такой диск может быть изготовлен с помощью того же Clone CDCloneCD и корпеть над написанием собственной "прожигалки" в этом случае не надо, что есть плюс.


Однако коль скоро для создания оригинального диска используется утилита массового распространения, процесс создания несанкционированных дубликатов значительно упрощается. Хакеру достаточно снять с диска корректный дамп, а все остальное —– это забота копировщика Clone CDCloneCD. Необходимость разрабатывать специализированный софт для взлома при этом отпадает. Один словом: все, что легко защищается, легко и ломается. Впрочем, квалифицированных хакеров не так уж и много и для предотвращения "утекания" своей продукции намс с вами достаточно добиться некопируемости ключевого диска распространенными копировщиками в автоматическом режиме. И, как мы увидим в дальнейшем, защита данного типа полностью удовлетворяет этому требованию.

Процесс подготовки защищенного диска не лишен определенных тонкостей. Создание фиктивного трека с нулевым номером не вызывает особых трудностей, но вот вопрос: где его разместить? В первой, а, может быть, лучше во второй сессии? До подлинного трека или после? Поскольку вводная область первой сессии недоступна для чтения на субканальном уровне, то прочитать TOC первой сессии вручную нельзя. Нельзя и закладываться расчитывать на команду READ TOC, поскольку, как уже было сказано ранеевыше, ее корректное выполнение не гарантируется. Вводные области второй и всех последующих сессий свободно доступны на субканальном уровне и ручное чтение хранимогого ими  TOC'а все таки возможно. Конкретная позиция нулевого трека внутри сессии особой роли не играет, и нулевой трек может быть с одинаковым успехом размещен как до ненулевого трека, так и после него.

Только, пожалуйста, не забывайте о необходимости коррекции point'а указателя A0h, хранящего номер "первого" трека всякой сессии. Если его значение оставить без изменений, то образ диска запишется без каких- либо препирательств со стороны Clone CDCloneCD, но никаких упоминаний о нулевом треке в TOC'е "прожженного" диска не окажется! Точно так же ведет себя и Alcohol 120%Алкоголь.


Чтобы этого избежать, значение point' а указателя A0h той сессии, к которой вы добавляете нулевой трек, должно быть сброшено в нольZero.

Фрагмент отредактированного CCD-файла приведен в листинге 6.41.ниже:

Листинг 6.41. Фрагмент CCD-файла с добавленным нулевым треком

TocEntries=13

TocEntries=14

; корректируем количество входов в TOC

[Entry 8]

[Entry 8]

; это вход не обязательно должен быть восьмым…

Session=2

Session=2

; …главное, чтобы Session == 2, а Point == A0h

Point=0xa0

Point=0xa0

; этот Point отвечает на номер первого трека

ADR=0x01

ADR=0x01

; это служебные поля ADR/Control, описывающие

Control=0x04

Control=0x04

; режим обработки трека (это трек с данными)

TrackNo=0

TrackNo=0

; TNO = 0 – это Lead-In область

AMin=0

AMin=0

; \

ASec=0

ASec=0

;  +- условный текущий абсолютный адрес

AFrame=0

AFrame=0

; /

ALBA=-150

ALBA=-150

; условный текущий LBA-адрес

Zero=0

Zero=0

; это поле всегда равно нулю

PMin=2 à

PMin=0

; корректируем номер "первого" трека

PSec=0

PSec=0

; эти поля не имеют никакого смысла и должны

PFrame=0

PFrame=0

; быть равны нулю

PLBA=8850

PLBA=8850

; LBA-"адрес" номера "первого" трека

[Entry 11]

; добавляем еще одно Entry, описывающее нулевой трек

Session=2

; нулевой трек должен быть не в первой сессии

Point=0x00

; номер трека - ноль

ADR=0x01

; Sub-channel Q encodes current position data

Control=0x04

; трек с данными

TrackNo=0

; это Lead-In

AMin=0

; \

ASec=0

;  + - условный абсолютный адрес Lead-In

AFrame=0

; /

ALBA=-150

; условный LBA-адрес Lead-In

Zero=0

; это поле должно быть равно нулю

PMin=3

; \

PSec=1

;  + - абсолютный стартовый адрес нулевого трека

PFrame=66

; /

PLBA=13458

; LBA-адрес нулевого трека

<


TocEntries=13   TocEntries=14   ; корректируем количество входов в TOC

[Entry 8]       [Entry 8]       ; это вход не обязательно должен быть восьмым…

Session=2       Session=2       ; …главное, чтобы Session == 2, а Point == A0h

Point=0xa0      Point=0xa0      ; этот Point отвечает на номер первого трека

ADR=0x01        ADR=0x01        ; это служебные поля ADR/Control, описывающие

Control=0x04    Control=0x04    ; режим обработки трека (это трек с данными)

TrackNo=0       TrackNo=0       ; TNO = 0 – это Lead-In область

AMin=0          AMin=0          ; \

ASec=0          ASec=0          ;  +- условный текущий абсолютный адрес

AFrame=0        AFrame=0        ; /

ALBA=-150       ALBA=-150       ; условный текущий LBA-адрес

Zero=0          Zero=0          ; это поле всегда равно нулю

PMin=2  à      PMin=0          ; корректируем номер "первого" трека

PSec=0          PSec=0          ; эти поля не имеют никакого смысла и должны

PFrame=0        PFrame=0        ; быть равны нулю

PLBA=8850       PLBA=8850       ; LBA-"адрес" номера "первого" трека

                [Entry 11]      ; добавляем еще одно Entry, описывающее нулевой трек

                Session=2       ; нулевой трек должен быть не в первой сессии

                Point=0x00      ; номер трека - ноль

                ADR=0x01        ; Sub-channel Q encodes current position data

                Control=0x04    ; трек с данными

                TrackNo=0       ; это Lead-In

                AMin=0          ; \

                ASec=0          ;  + - условный абсолютный адрес Lead-In

                AFrame=0        ; /

                ALBA=-150       ; условный LBA-адрес Lead-In

                Zero=0          ; это поле должно быть равно нулю

                PMin=3          ; \

                PSec=1          ;  + - абсолютный стартовый адрес нулевого трека

                PFrame=66       ; /

                PLBA=13458      ; LBA-адрес нулевого трека

Листинг 33 фрагмент CCD-файла с добавленным нулевым треком



При просмотре геометрии защищенного таким образом диска Ahead Nero выдает приблизительно следующую информацию (см. рис. 6.220x105)[6]. То, что он посчитал вторую сессию открытой ("Session is open") вполне объяснимо, так как созданный нами нулевой трек был ошибочно принят Ahead Nero Нероном за вводную область, в результате чего шаткое равновесие между вводными и выводными областям оказалось нарушенным. Между тем, вторая сессия диска все-таки закрыта и анализ TOC подтверждает это. А не знать, что упоминание о вводных областях никогда в явном виде не присутствует в TOC'е —– глупо. Разобраработаться, почему нулевой трек оказался приобщенретен Ahead Nero Нероном к первой сессии несколько сложнее. По видимому, это грубая алгоритмическая ошибка, которая не делает чести ни самому Ahead NeroНерону, ни его разработчикам.



Рис. 6.22. унок 17 0x105 Наличие нулевого трека на диске срывает крышу путает Ahead NeroНерону, вводя его в глубокое заблуждение относительно состояния последней сессии диска. Ahead Nero Нерон считает, что вторая сессии открыта, хотя на самом деле это не так .

Clone CDCloneCD ведет себя аналогичным образом и при попытке копирования защищенного диска на приводах ASUS и TEAC со всего маху "врезается" в выводную область первой сессии диска. Вторая сессия (с нулевым треком) по причине грубых алгоритмических ошибок полностью выпадает из его поля зрения и в TOC'е скопированного диска о ней даже и не упоминается. Стартовый адрес выводной области первой сессии так же определяется неправильно (Clone CDCloneCD устанавливает его на стартовый адрес нулевого трека второй сессии). Point'ы Указатели B0h (стартовый адрес следующей позиции для дозаписи) и C0h (стартовый адрес первой вводной области диска) то же оказываются потерянными. Короче говоря, TOC скопированного диска более чем существенно отличается от TOC'а оригинального и обнаружить факт несанкционированного копирования не составит никакого труда, да вы их сами сравните (листинг 6.42).


TOC оригинального ключевого диска с нулевым треком внутри второй сессии (слева) при чем атрибуты нулевого трека выделены серой заливкой и TOC его копии, полученной с помощью копировщика CloneCD (справа). Все несовпадения выделены полужирным шрифтом.:

Листинг 6.42. TOC оригинального ключевого диска с нулевым треком внутри второй сессии (слева) и TOC его копии, полученной с помощью CloneCD (справа)

01 14 00 A0 00 00 00 00 01 00 00

01 14 00 A0 00 00 00 00 01 00 00

01 14 00 A1 00 00 00 00 01 00 00

01 14 00 A1 00 00 00 00 01 00 00

01 14 00 A2 00 00 00 00 00 1D 21

01 14 00 A2 00 00 00 00 03 01 42

01 14 00 01 00 00 00 00 00 02 00

01 14 00 01 00 00 00 00 00 02 00

01 54 00 B0 02 3B 21 03 16 0E 22

 

01 54 00 C0 A2 C8 E0 00 61 1B 15

 

02 14 00 A0 00 00 00 00 02 00 00

 

02 14 00 A1 00 00 00 00 00 00 00

 

02 14 00 A2 00 00 00 00 03 18 17

 

02 14 00 00 00 00 00 00 03 01 42

 

 

Листинг 34 TOC оригинального ключевого диска с нулевым треком внутри второй сессии (слева, атрибуты нулевого трека выделены серой заливкой) и TOC его копии, полученной с помощью Clone CD (справа). Все несовпадения выделены жирным шрифтом.

При попытке копирования защищенного диска на приводе NEC (который, как уже отмечалось отказывается читать TOC с нулевым треком), копировщик Clone CDCloneCD удивленно спрашивает "диск пуст?" и вне зависимости от нашего ответа, даже и не пытается приступить к его копированию, вызывая страшный хакерский гнев и раздражение.

Alcohol 120% Алкоголь при попытке копирования защищенного диска просто "виснет", едва лишь успев перед смертью выбросить исключение "access violation" (нарушение доступа), но зато заблокировав лоток привода, так что без уменьшения счетчика блокировок извлечь диск помогает разве что тотальная перезагрузка системы.

В общем, дело —– мрак! (С точки зрения "пиратов" конечно).


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

Первое, что приходит нам в голову —– прочитать "сырой" TOC командой READ TOC и проверить наличие трека номер ноль, а для пущей надежности – и его атрибуты. Если нулевой трек действительно присутствует в TOC'е и его атрибуты (т. е. поля Session, ADR, Control, PMin:PSec:Pfarme) полностью соответствуют эталону, —– это оригинальный диск и, соответственно, наоборот. Достоинство такого алгоритма в том, что он очень просто реализуется, укладываясь буквально в десяток строк кода, а недостаток —– нестабильность опознавания ключевого диска на определенных моделях приводов. Привод может отказаться читать TOC и к такому повороту событий защита должна быть заранее готова. Давайте сделаем так: если команда READ TOC возвращает ошибку, но диск присутствует в приводе и не препятствует выполнению команды SEEK, то – это оригинальный диск. Конечно, подобное эвристическое допущение значительно ослабляет защиту, однако для большинства применений ее стойкости будет вполне достаточно.

Однако безошибочное выполнение команды READ CD еще не есть свидетельство того, что она выполнена успешно. Ни один известный мне привод, способный читать TOC с нулевым треком, не читает его правильно, а потому защита должна заранее учитывать характер возможных искажений TOC'а и адекватно ему противостоять.

Рассмотрим, например, какой результат возвращает привод TEAC (листинг 6.43). Нулевой трек выделен серой заливкой, а "мусор", следующий за ним — полужирным шрифтом.:

Листинг 6.43. Содержимое TOC ключевого диска, возращенное приводом TEAC

Номер сессии

|  ADR/Control

|  |  TNO

|  |  |  Point

|  |  |  |  |  AM:AS:AF PM:PS:PF

|  |  |  |  |  |  |  |  |  |  |

01 14 00 A0 00 00 00 00 01 00 00 ; point A0 – номер первого трека сессии 1 в PM



01 14 00 A1 00 00 00 00 01 00 00 ; point A1 – номер последнего трека сессии 1 в PM

01 14 00 A2 00 00 00 00 00 1D 21 ; point A2 – адрес Lead-out сессии 1 в PM:PS:PF

01 14 00 01 00 00 00 00 00 02 00 ; point 01 – стартовый адрес трека 1 в PM:PS:PF

01 54 00 B0 02 3B 21 03 16 0E 22 ; point B0 – позиция дозаписи в AM:AS:AF

01 54 00 C0 A2 C8 E0 00 61 1B 15 ; point C0 – стартовый адрес Lead-InLead-In в

                                 ; PM:PS:PF /искж

02 14 00 A0 00 00 00 00 02 00 00 ; point A0 - номер первого трека сессии 1 в PM

02 14 00 A1 00 00 00 00 00 00 00 ; point A1 – номер последнего трека сессии 2 в PM

02 14 00 A2 00 00 00 00 03 18 17 ; point A2 – адрес Lead-out сессии 2 в PM:PS:PF

02 14 00 00 00 00 00 00 03 01 42 ; point 00 – стартовый адрес трека 0 в PM:PS:PFpoint 00 – стартовый адрес трека 0 в PM:PS:PF

FB FD 00 FB F4 FB 7A FF FD FD FF ; \          | как видно, встретив нулевой трек, TEAC

FB DF 00 FA FD F5 FF BF FB FE FF ;  + - мусор | TEAC вместо осмысленных данных начал изры-

FE F7 00 FB FF FD FB FF FF F7 FF ; /          | начал изрыгать мусор

 

Листинг 35 содержимое TOC'а ключевого диска, возращенное приводом TEAC, нулевой трек выделен серой заливкой, а мусор, следующий за ним – жирным шрифтом

Что это за подозрительный мусор, расположенный следом за нулевым треком? Это —– содержимое внутренних буферов привода, попавшее сюда в результате грубой программистской ошибке в микропрограмме привода (между прочим, тестировалась самая свежая на момент написания этих строк прошивка —– 1.09). Небольшое "расследование" убедительно доказывает, что "мусор" носит не случайный харакер и представляет собой "хвост" TOC'а предыдущего диска.

Давайте, вставив в привод какой ни будь диск (например, "Soul Ballet Hit Collection"), заново сменим его на ключевой и посмотрим что у нас из этого получится (листинг 6.44).:

Листинг 6.44. TOC диска Soul Ballet (слева) и TOC ключевого диска (справа), возвращенные приводом TEAC



01 10 00 A0 00 00 00 00 01 00 00                    01 14 00 A0 00 00 00 00 01 00 00

01 10 00 A1 00 00 00 00 10 00 00                    01 14 00 A1 00 00 00 00 01 00 00

01 10 00 A2 00 00 00 00 48 1C 05                    01 14 00 A2 00 00 00 00 00 1D 21

01 10 00 01 00 00 00 00 00 02 00                    01 14 00 01 00 00 00 00 00 03 00

01 10 00 02 00 00 00 00 03 35 40                    01 54 00 B0 02 3B 21 03 16 0E 22

01 10 00 03 00 00 00 00 08 14 33                    01 54 00 C0 A2 C8 E0 00 61 1B 15

01 10 00 04 00 00 00 00 0C 21 0D                    02 14 00 A0 00 00 00 00 02 00 00

01 10 00 05 00 00 00 00 10 3A 2D                    02 14 00 A1 00 00 00 00 00 00 00

01 10 00 06 00 00 00 00 16 23 19                    02 14 00 A2 00 00 00 00 03 18 17

01 10 00 07 00 00 00 00 1C 1B 0C                    02 14 00 00 00 00 00 00 03 01 42

01 10 00 08 00 00 00 00 21 07 49                    09 25 00 1F 00 00 00 00 19 01 10

01 10 00 09 00 00 00 00 25 1F 19                    0A 2A 00 01 00 00 00 00 06 01 10

01 10 00 0A 00 00 00 00 2A 01 06                    0B 2D 00 2D 00 00 00 00 00 01 10

01 10 00 0B 00 00 00 00 2D 2D 00                    0C 33 00 29 00 00 00 00 02 01 10

01 10 00 0C 00 00 00 00 33 29 02                    0D 39 00 08 00 00 00 00 45 01 10

01 10 00 0D 00 00 00 00 39 08 45                    0E 3F 00 1E 00 00 00 00 27 01 10

01 10 00 0E 00 00 00 00 3F 1E 27                    0F 43 00 1E 00 00 00 00 29 01 10

01 10 00 0F 00 00 00 00 43 1E 29                    10 44 00 03 00 00 00 00 15 FF FF

01 10 00 10 00 00 00 00 44 03 15

Листинг 36 TOC диска Soul Ballet (слева) и TOC ключевого диска (справа), возвращенные приводом TEAC

Смотрите! Сейчас содержимое TOC'а ключевого диска существенно изменилось. Пускай не все содержимое, но вот "хвост" изменился точно. Причем, последовательность байт "хвоста" ключевого диска соотвествует последовательности байт диска "Soul Ballet". Пускай "…09 00 00 00 00 25 1F 19…" и "…09 25 00 1F 00 00 19…" и не совсем тождественные последовательности, но если убрать паразитные нули мы получим: "…09 25 1F 19…" и "…09 25 1F 19…", которые побайтно равны друг другу.


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

Привод ASUS ведет себя более корректно (листинг 6.45), просто "обрубая" TOC по нулевому треку, даже в том случае когда нулевой трек —– не последний трек диска, что тоже расценивается как микропрограммная ошибка, пускай и не такая грубая.

Листинг 6.45. TOC ключевого диска, возращенный приводом ASUS

01 14 00 A0 00 00 00 00 01 00 00

01 14 00 A1 00 00 00 00 01 00 00

01 14 00 A2 00 00 00 00 00 1D 21

01 14 00 01 00 00 00 00 00 03 00

01 54 00 B0 02 3B 21 03 16 0E 22

01 54 00 C0 A2 C8 E0 00 61 1B 15

02 14 00 A0 00 00 00 00 02 00 00

02 14 00 A1 00 00 00 00 00 00 00

02 14 00 A2 00 00 00 00 03 18 17

02 14 00 00 00 00 00 00 03 01 42

Привод Листинг 37 TOC ключевого диска, возращенный приводом ASUS

NEC, как уже говорилось ранеевыше, вообще не выдает ничего, кроме ошибки, которою защитный механизм вынужден интерпретировать как индикатор лицензионности диска, в противном случае разработчик может поплатиться своими яйцамисвоей головой, которуюые с удовольствием оторвут легальные пользователи, пытающиеся "скормить" защищенный диск "неправильному" (с точки зрения защиты) приводу.

Тем не менее, преднамеренное ослабление стойкости защиты —– это не выход. Уж лучше попробовать прочитать TOC вручную. Это достаточно трудно реализуется на программном уровне, но еще труднее "ломается"! Если команду READ TOC легко и проэмулировать, то воссоздать особенности обработки субканальных данных практически нереально, благодаря чему усиленный вариант защиты с легкостью обойдет все копировщики, эмулирующие виртуальные диски.

Опасаясь охладить ваш воинственный программистский пыл, я все же скажу: правильно считать субканальные данные не так-то просто, как это может показаться на первый взгляд и одних лишь спецификаций для успешной реализации защитного механизма мало. В них не отображено и доли тех "чудачеств" приводов, с которыми приходится сталкиваться на практике.



q      Первое и самое главное: абсолютные адреса секторов ни коим образом не связаны с "соответствующими" им субканальными данными, хотя бы уже потому, что одна секция субканальных данных "размазана" по нескольким секторам, причем в силу определенных конструктивных особенностей, обработка субканальных данных и данных основного потока осуществляется раздельно, благодаря чему при позиционировании головки на сектор N [Y177] [n2k178] X с последующим вызовом команды READ SUBCHANNEL, мы получим субканальные данные не сектора XN, ано сектора MY, лежащего "поблизости" от сектора NX. Понятие "поблизости" всяк производитель определяет самостоятельно, зачастую уползая не на одну сотню секторов вперед.

q      Второе: связка команд SEEK и /READ SUBCHANNEL неустойчива

и обладает хреновой плохой воспроизводимостью результатов. Никто не гарантирует, что позиционирование на сектор NX+k приведет к чтению субканальных данных сектора MY+k. Привод может возвратить как данные сектора MY, так и данные сектора MY+i. Так же никто не гарантирует, что повторное позиционирование не сектор NX приведет к чтению субканальных данных сектора MY. (кстати, не забывайте между двумя соседними вызовами командыами SEEK выдерживать паузу хотя бы в 1 сек, иначе головка просто не успеет переместиться на новое место и привод как ни в чем не бывало возвратит уже скэшированные субканальные данные с места предыдущего позиционирования). Остается опираться лишь на текущие адреса секторов, возвращаемые в самой субканальной информации (поле "Absolute CD Address"). Встретив в этом поле адрес "своего" сектора мы может быть абсолютно уверенными в том, что эта субканальная информация принадлежит именно "нашему" сектору, а не какому-то сектору еще.

Листинг 6.46. Правильная интерпретация субканальной информации

LBA - 10D4:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6D



^^^^^^^^^^                      ^  ^^^^^^^^^^^ ^^^^^^^^^^^

    |                           |       |            |

LBA-адрес  сектора, на  который | атрибуты point'a LBA-адрес сектора, чьи

осуществлялось позиционирование |                  чьи  субканальные данные

командой SEEK                 point осуществлялось позиционирование |                   данные возвратил привод

командой SEEK                 point

q       

q      Листинг 38 правильная интерпретация субканальной информации

q      Третье: конкретный формат субканальной информации определяется не стандартом, а самим приводом и значительно варьируется от одной модели к другой. Наиболее непостоянны в этом смысле вводные и выводные области диска. Стандарт вообще ничего не говорит о возможности их чтения на субканальном уровне, молчаливо полагая, что это никому на хрен и не нужно. Вот производители и "извращаются" в меру своей распущенности и фантазиий. Поля абсолютных и относительных адресов могут безо всяких предупреждений меняться местами, а сами адреса могут задаваться как в формате M:S:F, так и в LBA-форме. Значения point'ов указателей A0h, A1h и A2h (номер первого трека, номер последнего трека и адрес области Lead-outLead-Out области) могут замещаться значениями 64h, 65h и 66h соответственно. Наконец, нестандартные point'ы указатели (в том числе и нулевые point'ыуказатели) в субканальных данных зачастую попросту отсутствуют —– вместо этого возвращаются данные либо предыдущей, либо последующей секций!

Все это значительно усложняет интерпретацию субканальных данных и поиск в ней нулевых треков, поэтому приходится действовать так: последовательно читая субканальные данные различных секторов диска дожидаемся того момента когда номера треков сменяться сначала на AAh, а затем и на 00h, что будет соответствовать переходу головки с области Lead-outLead-Out области первой сессии на область Lead-inLead-In область второй сессий.


Продолжая читать Lead-inLead-In, мы попытаемся определить в какой закономерности изменяются поля абсолютных и относительных адресов и форму их представления (LBA или M:S:F). Собственно, формат представления определить очень легко. Если младший байт адреса принимает значения больше, чем 75 (4Bh), то – это, несомненно, – LBA и наоборот. Далее —– поскольку поля относительных адресов в вводной области диска используются для хранения атрибутов "своего" point'ауказателя, то они чрезвычайно сильно отличаются от текущих адресов секторов —– тех, на которых и осуществлялось позиционирование. Напротив, поля абсолютных адресов к текущим адресам должны быть достаточно близки.

Остается решить последнюю проблему —– что делать, если в субканальных данных Lead-inLead-In области нулевого трека попросту не окажется? Не спешите делать вывод о нелицензионности диска —– ведь, как уже было сказано ранеевыше, некоторые приводы нестандартные point'ы указатели просто не возвращают. При этом абсолютные адреса секторов, хранящих субканальные атрибуты нулевого трека, в считанном TOC'е не будут присутствовать! Копия диска, полученная любым из существующих на данный момент копировщиков, по данным абсолютным адресам будет содержать атрибуты совершенно других треков, которые привод вполне корректно прочитает и возвратит, либо же вовсе откажется позиционировать головку на эту область, выдавая ту или иную ошибку.

Ну, что, парни, слабо реализовать такое? Для облегчения восприятия материала ниже далее будут приведены субкальные данные ключевого диска, возращенные различными приводами. А подробные комментарии, щедро разбросанные автором, помогут разобраться что к чему.

Листинг 6.47. Резултат чтения субканальной информации из области Lead-In на приводе TEAC; отчетливо просматривается нулевой трек

            +internal+  Format

            |  |  |  |  |  ADR/Control

            |  |  |  |  |  |  TNO

            |  |  |  |  |  |  |  Point

            |  |  |  |  |  |  |  |  +- PLBA -+  +- ALBA -+



            |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |

LBA - 10D4: 00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6D ; LBA 10D4 à

116D


LBA - 10D5:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6D ; LBA 10D5 à

116D


LBA - 10D6:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6E

; LBA 10D5 à

116E


LBA - 10D7:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6D ; LBA 10D7 à

116D (!)


LBA - 10D8:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6E ; ("биение" головки)

LBA - 10D9:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6E ; LBA 2292 = 02:00:00

                                                           ; M:S:F

LBA - 10DA:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; LBA FFh – 6Ah = 95h

                                                           ; (149)

LBA - 10DB:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; LBA 149 == MSF 0:0:1

LBA - 10DC:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 74 ; что удивительно, т.к.

LBA - 10DD:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 75 ; последнего трека

                                                           ; должен

LBA - 10DE:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 74 ; быть в PM, но не в PF

LBA - 10DF:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 74 ; учитывайте это!

LBA - 10E0:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; продолжается биение го-

LBA - 10E1:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; головки: сектора идут не

LBA - 10E2:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7B ; не упорядочено:

                                                           ; 1179, 1179,

LBA - 10E3:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; 117B, 1179, 117A, 117A и

LBA - 10E4:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7A ; и нету секторов 1176, 1177

LBA - 10E5:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7A ; 1177 и 178

LBA - 10E6:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 80 ;

LBA - 10E7:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 80 ;

LBA - 10E8:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 80 ; биение головки



LBA - 10E9: 00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 7F ;             продолжается

LBA - 10EA:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 80 ;

LBA - 10EB:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 81 ;

LBA - 10EC:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; а вот и нулевой трек, он

LBA - 10ED:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; он располагается в

                                                           ; секторах секторах

LBA - 10EE:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 86 ; 1185 и 1186 – запомним

LBA - 10EF:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; это обстоятельство!

LBA - 10EF:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; это обстоятельство!

LBA - 10F0:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8C ; point A0 повторяется…

LBA - 10F1:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8C ; а вместе с ним и все

LBA - 10F2:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B ; остальные point'ы. Читая

LBA - 10F3:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B ; Читая субканальные

                                                           ; данные дальше мы вновь -

LBA - 10F4:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8C ; ше мы вновь встретим нулевой трек,-

LBA - 10F5:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B ; левой трек, но уже в других -

LBA - 10F6:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B ; гих секторах. Запомним и

LBA - 10F7:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B ; ихз для надежности

Листинг 39 резултат чтения субканальной информации из Lead-In на приводе TEAC; отчетливо просматривается нулевой трек

Здесь абсолютные адреса представлены в LBA-форме, причем расхождение между адресом на который осуществляется позиционирование головки и адресом, чьи субканальные данные при этом читаются (далее по тексту —– дельта) составляет порядка –400 секторов. Правда, равномерность "часового хода" очень хороша, абсолютные идут кучным пучком строго социалистического характера, хотя TEAC все-таки не без греха и оплошности типа 11:6D, 11:6E, 11:6D, 11:6E случаются сплошь и рядом.


Атрибуты нулевого трека присутствуют в явном виде, что не может не радовать.

А вот привод ASUS ведет себя более "разболтано" (листинг 6.48).:

Листинг 6.48. Результат чтения субканальной информации из Lead-In на приводе ASUS

            +internal+  Format

            |  |  |  |  |  ADR/Control

            |  |  |  |  |  |  TNO

            |  |  |  |  |  |  |  Point

            |  |  |  |  |  |  |  |  +- PLBA -+  +- ALBA -+

            |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |

LBA - 10D3:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; здесь субканальные данные

LBA - 10D4:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; данные возвращаются еще более

LBA - 10D5:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; еще более беспорядочно, и потому

LBA - 10D6:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; беспорядочно, и потому

                                                           ; отделить соседние point'ы

LBA - 10D7:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; point'ы друг от друга уже не

LBA - 10D8:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; уже не удается, между тем они

LBA - 10D9:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; тем они лежат по тем же самым

LBA - 10DA:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; же самым ALBA адресам, что и в

LBA - 10DB:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; что и в предыдущем случае, а

LBA - 10DC:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; случае, а потому, ALBA адреса могут

LBA - 10DD:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 6F ; адреса могут служить надежной опорой

LBA - 10DE:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; надежной опорой в идентификации point'ов

LBA - 10DF:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 73 ; идентификации point'ов не зависящей от насторо-

LBA - 10E0:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; не зависящей от ения, разболтанности

LBA - 10E1:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; настороения, разбол-и конструктивных особен-



LBA - 10E2: 00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 79 ; танности и конструк-ностей конкретных моделей

LBA - 10E3:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 75 ; тивных особенностей приводов, что значительно

LBA - 10E4:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7A ; конкретных моделей

                                                           ; приводов, что значи-

                                                           ; тельно упрощает процедуру про-

LBA - 10E5:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 75 ; процедуру проверки степени лицензион-

LBA - 10E6:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 80 ; степени лицензионной

                                                           ; "чистоты" анализиру-

LBA - 10E7:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 81 ; емого диска…

LBA - 10E8:00 15 00 0C 01 14 00 A1 00 FF FF 6A 00 00 11 75

LBA - 10E9:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7B

LBA - 10EA:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; атрибуты трека 0, обрати-

LBA - 10EB:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 81

LBA - 10EC:00 15 00 0C 01 14 00 A2 00 00 3B 45 00 00 11 7B

LBA - 10ED:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; обратите внимание, что

 они рас-

LBA - 10EE:00 15 00 0C 01 14 00 02 00 00 34 92 00 00 11 81

LBA - 10EF:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 86 ; они располгаются по тем же LBA

LBA - 10F0:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B

LBA - 10F1:00 15 00 0C 01 14 00 00 00 00 34 B3 00 00 11 85 ; тем же LBA адресам:

                                                           ; 1185h и 1186!

LBA - 10F2:00 15 00 0C 01 14 00 A0 00 00 22 92 00 00 11 8B

Листинг 40 результат чтения субканальной информации из Lead-In на приводе ASUS

Здесь: абсолютные адреса так же представлены в формате LBA и дельта составляет все те же 400 секторов, однако, степень неупорядоченности возвращаемой информации значительно выше и номера секторов начинают потихонечку "плясать" (листинг 6.49) (обратите внимание насм.


поле ALBA).

Листинг 6.49.  Результат чтения субканальной информации из Lead-In приводом NEC

            +internal+  Format

            |  |  |  |  |  ADR/Control

            |  |  |  |  |  |  TNO

            |  |  |  |  |  |  |  Point

            |  |  |  |  |  |  |  |  +- ALBA -+  +- PLBA -+

            |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |

LBA - 1171:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; point 64 – это на самом

LBA - 1172:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; самом деле point A0 (номер пер-

LBA - 1173:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; (номер первого трека), просто глу-

LBA - 1174:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; просто глупый привод так нелепо его

LBA - 1175:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; так нелепо его исказил, так же обратите

LBA - 1176:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; исказил, так же

                                                           ; обратите внимание, что

                                                           ; все адреса идут к все адреса

LBA - 1177:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; сектору 116E!; идут к сектору 116E!

LBA - 1178:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00 ;  резкий переход адресов переход адресов

LBA - 1179:00 15 00 0C 01 14 00 64 00 00 11 6E 00 02 00 00 ; с 116E на 1174 (+6) с 116E на 1174 (+6)

LBA - 117A:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00 ; такова дискретность такова дискретность SEEKа

LBA - 117B:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00 ; SEEKа привода NEC!

привода NEC!

LBA - 117C:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00

LBA - 117D:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00

LBA - 117E:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00

LBA - 117F:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00

LBA - 1180:00 15 00 0C 01 14 00 65 00 00 11 74 00 00 00 00

LBA - 1181:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45

LBA - 1182:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45



LBA - 1183: 00 15 00 0C 01 14 00 02 00 00 11 7F 00 00 34 92 ; 117F – …

LBA - 1184:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45

LBA - 1185:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45

LBA - 1186:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45

LBA - 1187:00 15 00 0C 01 14 00 02 00 00 11 81 00 00 34 92 ; 117F – 1181 диапазон

LBA - 1188:00 15 00 0C 01 14 00 02 00 00 11 7F 00 00 34 92 ; адресов, занятых субка-

LBA - 1189:00 15 00 0C 01 14 00 02 00 00 11 7F 00 00 34 92 ; субканальной информацией

LBA - 118A:00 15 00 0C 01 14 00 02 00 00 11 81 00 00 34 92 ; информацией

point'a == 2

LBA - 118B:00 15 00 0C 01 14 00 02 00 00 11 80 00 00 34 92 ; point'a == 2

LBA - 118C:00 15 00 0C 01 14 00 02 00 00 11 81 00 00 34 92

LBA - 118D:00 15 00 0C 01 14 00 66 00 00 11 7A 00 00 3B 45

LBA - 118E:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; смотрите! резкий переходпере-

LBA - 118F:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; ход с адреса 1181 на адрес

LBA - 1190:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; адрес 118B – 10 секто-ров пропу-

LBA - 1191:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; ров пропущено, причем это не прсто

LBA - 1192:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; это не прсто биение головки – этих

LBA - 1193:00 15 00 0C 01 14 00 64 00 00 11 8D 00 02 00 00 ; головки – этих секто-ров в субканальных

LBA - 1194:00 15 00 0C 01 14 00 64 00 00 11 8D 00 02 00 00 ; ров в субканальных

                                                           ; дДанных нет вообще! И как

LBA - 1195:00 15 00 0C 01 14 00 64 00 00 11 8B 00 02 00 00 ; И как раз в них и содержатся

LBA - 1196:00 15 00 0C 01 14 00 65 00 00 11 92 00 00 00 00 ; содержатся атрибуты трека ноль, а

LBA - 1197:00 15 00 0C 01 14 00 65 00 00 11 92 00 00 00 00 ; трека 0, а раз так, то то трек ноль все

LBA - 1198:00 15 00 0C 01 14 00 65 00 00 11 92 00 00 00 00 ; трек 0 все-таки есть есть на диске (иначе

LBA - 1199:00 15 00 0C 01 14 00 65 00 00 11 92 00 00 00 00 ; на диске (иначе бы эти



                                                           ; бы эти сектора возращ.)

Листинг 41  результат чтения субканальной информации из Lead-In приводом NEC

Здесь: дельта "уползания" составляет порядка 10  секторов, а зачастую даже менее того, однако, сама упорядоченность секторов вообще никакая, а нулевых point'ов указателей вообще нет. Сектора с адресами 1185h и 1186h (в которых собственно и храняться атрибуты нулевых треков) "в наглую" отсутствуют —– вместо этого привод спозиционировал головку на адреса 118Bh и 118Dh, в результате чего количество 64h point'ов указателей (в "девичестве" —– A0h) до неприличия возросло. Ко всему прочему абсолютные адреса секторов по непонятной причине перекочевали в поле относительных адресов, и если бы мы попытались проанализировать субканальную информацию согласно стандарту, у нашей защиты точно бы "съехала крыша".

Итак, несмотря громоздкость и трудности реализации защитного механизма, он все-таки может быть реализован так, чтобы уверенно отличать ключевой диск на любой из моделей приводов. Но стоит ли овчинка выделки или, говоря другими словами, каким образом защищенный диск можно взломать?

А вот со взломом у нас туго. Да, в принципе такой диск можно скопировать, но только не с помощью Сlone CD или Alcohol 120% Алкоголем и не на всех моделях приводах. Для взлома пригодны лишь те приводы, что уверенно читают TOC и возвращают атрибуты нестандартных point'овуказателей, поскольку ко всему этому может привязываться защита. Постойте! —– воскликните вы, —– но ведь защита не должна опиратьсязакладываться на доступность TOC'а и атрибуты нулевого point'ауказателя, иначе программа окажется неработоспособна на некоторых моделях приводов! Это верно, однако, если привод соглашается читать TOC — – отчего же его не проверить?

Если привод взломщика не позволяет читать содержимое TOC, взломщик не сможет восстановить оригинальный TOC (ну разве что отдизассемблирует весь защитный механизм целиком) и потому скопированный диск будет работать лишь на его приводе!

Правда при наличии привода, читающего TOC и "хорошо смазанных подшипников в котелке", копирование защищенного диска осуществляется очень просто. Достаточно лишь считав TOC (команда READ TOC), считать и само содержимое диска на субканальном уровне (команды SEEK или /READ SUBCHANNEL), а так же содержимое основного канала (команда READ CD), после чего остается лишь сформировать CCD-, -IMG- и SUB-файлы и с помощью того же копировщика Clone CDCloneCD записать их на диск. Однако, на такой взлом "по зубам" далеко не всякому хакеру, а с натиском желторотых пользователей эта защита без труда справится.


Содержание раздела