TURBO PASCAL |
Новости
|
7.2.5. Использование скрытых частей программы и особенностей физических носителей информацииДостаточно эффективным способом защиты (главным образом для мобильных программ) может служить создание и использование скрытых частей программы и/или особенностей физических носителей информации. Скрытые части программы — это участки дискового носителя, тем или иным способом связанные с программой, но не зафиксированные в качестве файлов ДОС. В подавляющем большинстве случаев программе нет необходимости искусственно создавать такие участки, поскольку они уже имеются в «хвосте» любого файла. Дело в том, что ДОС распределяет дисковое пространство кластерами, имеющими длину от 512 до 4096 и более байтов. Даже если полезная длина файла составляет всего несколько байт, ДОС выделяет такому файлу целый кластер, большая часть которого будет заполнена «мусором» — случайной информацией, сохранившейся от предыдущего использования кластера в составе другого файла. При копировании файлов стандартными средствами ДОС копируется только полезная часть кластера, так что на новом месте «хвост» файла в общем случае будет заполнен другой информацией. Следующий простой пример иллюстрирует использование скрытой части файла для защиты программы от нелегального копирования. В этом примере программа управляется с помощью параметра запуска «/S»: если команда запуска программы дополнена этими символами, программа вводит с клавиатуры произвольную строку и помещает ее в «хвост» файла, в противном случае читает строку с диска и выводит ее на экран. _•+——————————.——————————————————+ I Программа создает и контролирует скрытую \ ¦ часть файла. При запуске без ключа /S \ '. осуществляется контроль файла, при запуске ¦ i с ключом - создание скрытой части. ¦ +—————————.———,————————————————+/ var F: File; {Файловая переменная для файла программы} S: String; {Переменная для создания скрытой части} L: Longint; 'Полезная длина файла} begin Assign(F,ParamStr(0)) ; 'Reset(P,1) ; L := FileSize(F) ; WriteLn('Гарантированный остаток: ', mod 512,' байт'); Seek(F,L); {Указатель - в конец файла} if ParamStr(1)='/S' then begin {Создаем скрытую часть} WriteLn('Введите произвольную текстовую строку'); ReadLn(S); BlockWrite(F,S,succ (Length(S))) ; Seek(F,L); {Восстанавливаем...} Truncate(F) {...прежнюю длину файла} end else begin {Проверяем скрытую часть} Seek(F,L+256); {Увеличиваем длину файла} BlockWrite(F,S,1); {на 256 байт, чтобы исключить ошибку чтения из "хвоста" файла} Seek(F,L) ; BlockRead(F,S,256) ; WriteLn('Скрытая часть файла:'); WriteLn (S) ; Seek(F,L); {Восстанавливаем} Truncate(F) {прежнюю длину файла} end; Close(P) end. Более изощренный, но ничуть не более эффективный способ защиты состоит в создании и использовании дополнительных скрытых кластеров. Такие кластеры могут помечаться в FAT как сбойные или «потерянные» (т.е. не относящиеся ни к какому зарегистрированному файлу). Во всех случаях, помещается ли ключ в хвост файла или в отдельный кластер, защита может быть легко нейтрализована, если используется копирование дискеты «блок в блок» с помощью системной утилиты DISKCOPY или аналогичных несистемных программ. Существенно лучшей способностью противостоять попыткам нелегального копирования обладает система защиты, основанная на учете индивидуальных особенностей дискет, прежде всего на анализе неустранимых дефектов. В этом случае система проверки защиты «знает» список дефектных секторов оригинальной дискеты и пытается их отформатировать. Если после форматирования обмен информацией с сектором проходит нормально, значит соответствующий сектор — бездефектный и, следовательно, мы имеем дело с нелегальной копией дискеты. Главное достоинство этого способа защиты заключается в принципиальной Невозможности создать программными средствами на нормальной дискете неустранимые дефекты. Как показывает практика, лишь очень небольшое число дискет (менее 1%) имеет заводские дефекты изготовления, поэтому при массовом тиражировании коммерческих программ приходится создавать такие дефекты искусственно. Для этого иногда используются лазеры, а чаще — обыкновенная булавка. После некоторой тренировки Вы всегда сможете наносить царапины на слой носителя или даже прокалывать дискету так, чтобы по возможности сохранить работоспособность большей ее части. Однако следует иметь в виду, что царапины и проколы на поверхности дискеты могут повредить считывающие головки накопителя. Следующая программа выводит на экран номера всех секторов дискеты, имеющих неустранимые дефекты. Программа сначала определяет истинное количество дорожек Trk и секторов NS на дорожке дискеты (в привод дисковода, рассчитанного на дискеты 1.2 Мбайт, может быть вставлена дискета емкостью 360 Кбайт). Проверка этих параметров осуществляется непосредственно по блоку параметров BIOS (BPB], считываемому из загрузочного сектора дискеты. После этого соответствующим образом изменяется таблица параметров дискеты (ТПД) и осуществляется цикл чтения по всем Trk дорожкам. Если в ходе чтения возникла ошибка, про — грамма приступает к детальному анализу дорожки. Она вначале пытается прочитать и запомнить информацию, содержащуюся в каждом из ее N5 секторов на обеих поверхностях, затем форматирует дорожку и восстанавливает прежнее содержимое секторов. Если после такой операции на дорожке останутся сбойные секторы, программа выводит на экран их номера. {+—— ————------—-------——----------——--+ ¦ Программа считывает информацию с дискеты по I дорожкам. При обнаружении сбойной дорожки ¦ определяется сбойный сектор, информация из I остальных секторов запоминается, а дорожка ' форматируется заново, после чего восстана- ', вливается содержимое несбойных секторов. I Если при повторной проверке вновь возникла ч ошибка, печатается фраза ¦ "Дефектный сектор NNN". +---------------------------------------------т/ Uses DOS, F_Disk; type PDBT_Type ^DBT^Type; {Указатель на ТПД} {Таблица параметров дискеты} DBT_Type = record Reservl array [0..2] of Byte; SizeCode Byte; {Код размера сектора} LastSect Byte; {Количество секторова дорожке} Reserv2 array [5..7] of Byte; FillChar Char; {Символ-заполнитель для форматирования} Reserv3 : Word end; {Элемент буфера форматирования} F_Buf = record Track: Byte; {Номер дорожки} Head : Byte; {Номер головки} Sect : Byte; {Номер сектора} Size : Byte {Код размера} end; TrackType = array [O..MaxInt] of Byte; const DSK = 0; {Номер диска} var Info: TDisk; {Информация о диске} Old: PDBT_Type; {Указатель на исходную ТПД} DBT: PDBT_Type; {Указатель на новую ТПД} TRK: Word; {Количество дорожек} NS : Word; {Количество секторов на дорожке} i, {Счетчик поверхностей} j, /Счетчик секторов} k, {Счетчик дорожек} nn: Integer; {Номер сектора в цилиндре} Р:"TrackType; {Буфер чтения/записи} R: registers; {Регистры ЦП} BF : array [0..20] of F_Buf; {Буфер для форматирования} begin {Определяем количество дорожек, головок и количество секторов на дорожке} GetDiskInfo(DSK,Info) ; if Disk_Error then begin WriteLn('Ошибка доступа к диску'); Halt end; Trk := Info.Tracks; NS := Info.TrackSiz; {Резервируем память для буфера} GetMem(P,2*NS*512) ; (Готовим нужную ТПД} Old := ptr(MemW[0:$lE*4+2],MemW[0:$1Е*4]); New(DBT) ; DBT^:= Old"; {Получаем копию ТПД в ОЗУ} SetIntVec($1E,DBT); {Изменяем ссылку на ТПД} DBT^ .Last-Sect := NS; {Устанавливаем нужное количество секторов на дорожке} {Цикл проверки дорожек} for k := 0 to TRK-1 do with R do begin ah := 2; {Код операции чтения} al := 2*NS; {Количество секторов чтения} ch := k; {Номер дорожки} с1 := 1; {Начать с 1-го сектора) dh := 0; {Начать с 0-й поверхности} dl := DSK; {Номер диска} es := seg(pл) ; bx := ofs (p") ; Intr($13,R); {Читаем всю дорожку} if (Flags and FCarry)<>0 then begin {Обнаружена сбойная дорожка} {Читаем дорожку по секторам} for i := 0 to I do {2 поверхности} for j := 1 to MS do begin ah := 2; {Код операции чтения} al := 1; {Читаем один сектор} ch := k; {Номер дорожки} с1 := j; {Номер сектора} dh := i; {Номер головки} dl := DSK; {Номер диска} nn := i*NS+pred(j) ; es := seg{p^[nn*512}) ; bx := seg(P/\[nn*512]) ; Intr($13,R) {Читаем сектор} end; {Форматируем дорожку} for i := 0 to 1 do begin {Цикл по головкам} for j := 1 to NS do with BF[j] do begin {Готовим буфер} Track:= k; Sect :° j; Head := i; Size := OlcT.SizeCode end; ah =5; {Операция форматирования} al = NS; {Количество секторов на дорожке} ch == k; {Номер дорожки} с1 =1; {Начать с 1-го сектора} dh = i; {Номер головки} dl = DSK; {Номер диска} es = seg(BF) ; bx = ofs(BF) ; Intr($13,R); {Форматируем поверхность} end; {Восстанавливаем содержимое дорожки и заново проверяем секторы} for i := 0 to 1 do {2 поверхности} for j := 1 to NS do begin {Восстанавливаем содержимое сектора} ah : = 3; {Код операции записи} а1 := 1; {Записываем 1 сектор} ch := k; {Номер дорожки] • с1 := j; {Номер сектора} dh := i; {Номер головки} dl := DSK; {Номер диска} пп := i*NS+pred(j) ; es := seg(PA[nn*512]) ; bx := ofs(P"[nn*512]); Intr($13,R) ; {Читаем сектор) ah := 2; /й'од операции чтения} а1 := 1; {Читаем 1 сектор} ch := k; {Номер дорожки} с1 :== j; {Номер сектора} dh :== i; {Номер головки} dl := DSK; {Номер диска} es := seg{P^[nr\*512] ) ; bx := ofstP^nr^S:!^]) ; Intr($13,R) ; if (Flags and FCarry)<>0 then WriteLn('Дефектный сектор ',(k*2+i)*NS+j) end end end; SetIntVec($lE,01d) {Восстанавливаем прежнюю ТПД} end. Недостатком описанного способа защиты являются относительно большие затраты времени на контроль всей дискеты и потеря работоспособности некоторой ее части. От этих недостатков можно избавиться, если на дискете создать программным способом нестандартные для ДОС особенности. Этими особенностями могут быть: • нестандартная длина секторов на всей дискете или какой-либо одной ее дорожке; • специальное расположение (фактор чередования) секторов на дорожке; • нестандартное количество дорожек. Разумеется, надежность защиты с помощью программно создаваемых особенностей структуры дискеты будет значительно меньше. Тем не менее следует помнить, что в большинстве случаев «взломщик» программы стремится изменить ее код, а не имитировать особый способ копирования дискет, так что несложная защита, связанная с использованием допол— нительной дорожки, может оказаться ничуть не хуже, чем защита с помощью «лазерной дырки». Как известно, ДОС может оперировать только с секторами длиной по 512 байт (исключением является создание утилитой VDISK виртуальных электронных дисков, размер секторов которых может отличаться от 512 байт). В то же время контроллеры ГД способны создавать и использовать секторы другого размера — по 128, 256 или 1024 байт. При обнаружении сектора нестандартного размера ДОС считает этот сектор сбойным, что можно использовать для защиты программы. Далее, дорожки на диске располагаются так, что самой внешней является нулевая дорожка, а самой внутренней — дорожка с максимальным номером. Обычно ДОС использует одинаковое количество секторов на всех дорожках, поэтому угловой размер каждого сектора постоянен, а следовательно, плотность записи информации растет с ростом номера дорожки. Количество секторов на дорожке и дорожек на дискете ДОС назначает так, чтобы даже для самой внутренней дорожки эта плотность не превысила некоторого значения, еще гарантирующего уверенную работу схем контроллера ГД. На практике оказывается, что подавляющее большинство современных контроллеров способно обслуживать большее количество дорожек, чем принято в ДОС. В целях защиты от копирования программа может создать и использовать одну или несколько дополнительных дорожек, но не вносить их в список «видимых для ДОС», т.е. не изменять поле BPB.TotSecs в загрузочном секторе, указывающее общее количество секторов на диске. Разумеется, возможен и другой вариант: можно «украсть» у ДОС несколько дорожек, уменьшив стандартное значение этого поля, однако нестандартная емкость дискеты легко обнаруживается, что снижает эффективность защиты. Заметим, что дополнительные дорожки могут отделяться от основной рабочей зоны дискеты неотформатированным интервалом, что может затруднить их обнаружение специальными программами копирования. Наконец, программа может использовать нестандартный фактор чередования секторов. Напомню (см. гл.3), что этот фактор влияет на время чтения/записи группы смежных секторов. Если какую-либо дорожку отформатировать с намеренно неоптимальным фактором чередования, время чтения этой дорожки может оказаться заметно больше, чем при чтении любой другой дорожки — вот Вам и еще один способ защиты! В приводимой в прил.ПЮ.1 программе Diskette иллюстрируется использование всех трех перечисленных параметров. На дискете емкостью 360 Кбайт создается 41—я дорожка с девятью секторами размером по 256 байт, причем для нее используется обратный фактор чередования, т.е. секторы на дорожке размещаются в последовательности 9,8,...,2,1. После этого в первый сектор новой дорожки записывается произвольная информация, затем сектор читается и проверяется правильность операций записи—чтения. В конце программы измеряется время доступа к новой дорожке и стандартной дорожке. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |