TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

П10. МОДУЛЬ F_PROT ДЛЯ ЗАЩИТЫ ПРОГРАММ ОТ НЕЛЕГАЛЬНОГО КОПИРОВАНИЯ

 Программа Diskette для подготовки ключевой дискеты<

Описание программы см. п.7.2.5.

/

+_-__----_-------------------—--—-------------+

¦ Форматирование дорожки нестандартными секто- ¦ ¦ рами с помощью прерывания $13. Используется ¦ ¦ дисковод 5 1/4 дюймов в режиме 360 Кбайт. ¦ ¦ Эта программа готовит дискету для работы \ ¦ с модулем F_Prot. \ +--__----------------.------_-------------------+;

Program Diskette-Uses DOS,F_disk;

const

TRK = 40; {Номер нестандартной дорожки} DSK =- 0; {Номер диска} SIZ = 1; {Код размера сектора} type

PDBT_Type ^DBTJType; {Указатель на ТПД1 {Таблица параметров дискеты} DBT_Type = record

Reservl array [0..2] of Byte;

SizeCode Byte; {Код размера сектора}

LastSect Byte; {Количество секторов на дорожке!

Reserv2 array [5..7] of Byte;

FillChar Char; {Символ-заполнитель форматирования} ReservS Word

end;

{Элемент буфера форматирования} F_Buf = record

Track: Byte; {Номер дорожки)

Head : Byte; {Номер головки}

Sect : Byte; {Номер сектора}

Size : Byte {Код размера} end;

var

Old: PDBT_Type; {Указатель на исходную ТПД) /—-___————___——;

Procedure Intrl3(var R: registers; S: String);

[Обращается к прерыванию 13 и анализирует ошибку (CF=1 - признак ошибки). Если ошибка обнаружена, печатает строку S и завершает работу программы} begin

Intr($13,R) ;

if R. Flags and FCarryoO then

if R.ah о б then {Игнорируем ошибку от смены типа дискеты} begin

WriteLn(S) ;

SetIntVec($lE,01d); {Восстанавливаем старую ТПД} Halt end end; {Intrl3} ^_____-__————___;

Function AccessTime(DSK,TRK: Byte): Real;

{Измеряет время доступа к дорожке и возвращает его своим результатом (в секундах) } var

Е: array [1..9*512] of Byte;

t,k: Longint;

R: registers;

begin

t :- MemL[0:$046C] ;

while t=MemL[0:$046C] do;

for k :- 1 to 10 do with R do begin

ah :- 2;

al := 9;

ch := TRK;

cl :- 1;

dh := 0;

dl := DSK;

es :- seg (E) ;

bx := ofs(E) ;

Intrl3(R,'Error') end;

AccessTime :- (MemL[0:$O46C]-t-1)*0.055

end;

/——————————;

var

B: array [1..9] of F Buf; {Буфер для форматирования}

k,N: Integer; {Счетчик цикла}

R: registers; {Регистры}

DBT: PDBT_Type; {Указатель на новую ТПД}

С,О: array [1..1024] of Byte; {Буферы чтения/записи)

Size: Word; {Длина сектора}

Info: TDisk;

begin {Главная программа}

ReadLn(C[200]);

C[17] := 0;

{Считаем контрольную сумму} М := 0;

for k := 2 to 255 do N := N+C[k];

C[256] := M mod 256;

{Шифруем сектор}

С[1] := Random(255)+1;

for k := 2 to 256 do C[k] :» C[k] xor C[1] ;

{Записываем сектор}

ah := $03; {Код операции записи)

а1 :-=• 1; {Записать 1 сектор}

ch :- TRK; {На дорожке TRK}

с1 := 1; {Начиная с сектора 1}

dh := 0; ^На поверхности 0}

dl := DSK; №ск DSK1

es := seg(C); {Адрес буфера С для записи}

Ьх :-. ofs(C) ;

Intrl3(R,'Ошибка записи');

{Читаем сектор)

ah := $02; ^Код операции чтения) а1 :=• 1;

ch := TRK;

с1 :- 1;

dh :- 0;

dl := DSK;

es := seg(D); {Адрес буфера D для чтения) Ьх :» ofs(D) ;

Intrl3(R,'Ошибка чтения') end;

{Проверяем совпадение) for k := I to Size do if c[k:]<>d[k] then begin

WriteLn('Несовпадение данных') ;

SetIntVec($lE,01d) ;

Halt end;

WriteLn('Создана и проверена ',TRK+1,

'-я дорожка с секторами по ',Size,' байт');

{Измеряем время доступа к новой дорожке)

Write('Время доступа к скрытой дорожке: ');

MriteLn(AccessTime(DSK,TRK):6:2,' с') ;

{Измеряем время доступа к стандартной дорожке)

DBTA.SizeCode := 2; {Указываем стандартную длину сектора в ТПД} Write('Доступ к обычной дорожке: ');

WriteLn(AccessTime(DSK,20):6:2,' с') ;

{Восстанавливаем старую ТПД}

SetIntVec($lE,01d) end.

П10.2. Модуль F_Prot

Описание модуля см. п.7.4.

^»=-«==»=====»=; unit F_Prot; {"»..-"=—==-="=»}

{

+--_----—---—-._------——-——---------—-——-,+

Модуль используется для защиты программ от ¦ нелегального копирования. Мобильный вариант ¦ программы защищается с помощью ключевой ди- ¦ скеты, стационарный вариант - за счет кон- ) троля даты создания ПЗУ. I +—————————————————————————————+;

INTERFACE Procedure ProtCheck(var P1,P2; var Res: Integer);

{Проверяет легальность копии:

PI - адрес процедуры NORMA; P2 - адрес процедуры ALARM;

Res - результат работы:

0^: был вызов NORMA;

1: был вызов ALARM;

2: не вставлена дискета. Любое другое значение может быть только при трассировке программы}

Function SetOnHD: Integer;

(Устанавливает копию на жесткий диск. Возвращает:

-1 - не вставлена дискета;

-2 - не мастер-дискета;

-3 - защита от записи или ошибка записи;

-4 - программа не скопирована на ЖД;

-5 - ошибка доступа к ЖД;

-6 - исчерпан лимит установок;

-7 - программа уже установлена;

>—0 - количество оставшихся установок}

Function RemoveFromHD: Integer;

{Удаляет копию с жесткого диска. Возвращает:

-1 - не вставлена дискета;

-2 - не мастер-дискета;

-3 - защита от записи или ошибка записи ГД;

-4 - программа не скопирована на ЖД;

-5 - ошибка доступа к ЖД;

>=0 - количество оставшихся установок}

IMPLEMENTATION Uses DOS,F_Disk;

type

TDate = array [1..4] of Word;

TKey = record case Byte of

0: (

Hard: Word; (Ключ для шифровки данных} Dat : TDate); {Дата создания ПЗУ}

1:(KeyW: array [1..5] of Word);

end;

const

TRK = 40; (Номер дорожки}

HED =0; {Номер головки}

SEC =1; {Номер сектора}

SIZ = 1; {Код размера секторов}

ETracks - 40; /Эталонное количество дорожек на дискете!

ETrackSiz - 9; {Эталонное количество секторов на дорожке}

Кеу:ТКеу - (KeyW:(О,О,О,О,0)); {Ключ стационарной программы} ;•-——————————;

Procedure TrassBlockl;

{Макрос для борьбы с трассировкой с помощью модификации команды} inline ( {ВО:}

$ОЕ/ {push cs}

$E8/$00/$00/ {call 61} {@1:}

$5В/ {pop bx}

$83/$ЕВ/$04/ {sub bx,@l-@0)

$07/ {pop es}

$53/ {push bx}

$B4/$C3/ {mov ah,$C3}

$26/$88/$67/$11/$90/ {mov es:[Ьх+в2-в0],ah} i@2:}

$90/ {пор}

$B4/$9O/ {mov ah, $90}

$26/$88/$б7/$11/$90/ {mov es:1Ьк+в2-@0],ah]

$5B); {pop by.) ^————.——————__^

Procedure TrassBlock2;

{Борьба с трассировкой с помощью контроля времени} vac

tl,t2: Longint;

label

Loop;

begin Loop:

tl := MemL[0:$046Cl ;

t2 := 0;

while MemL[O:$O46C]=tl do;

while MemL[0:$O46C]<tl+2 do inc(t2) ;

if t2<500 then goto Loop;

TrassBlockl end; {TrassBlock2} ^————————————;

type

TBuf = array [1..256] of Byte;

var

P: Pointer; {Ссылка на врежнюю ТПД} Buf: TBuf; {Буфер чтения/записи сектора} R: registers; {Регистры} _—.—— _——————_-;

Function DiskettPrepare(var DSK: Byte): Boolean;

type

DBT Type aE record {Структура таблицы параметров дискеты} Reservl : array [O..2] of Byte;

SizeCode: Byte; {Код размера сектора} LastSect: Byte; {Количество секторов на дорожке} Reserv2 : array [5..10] of Byte end;

var

Info: TDisk;

DBT,01dDBT:^DBT_Type;

begin {Проверяем наличие дискеты}

DSK := 0; {Начинаем с диска А:} repeat

TrassBlockl;

GetDiskInfo(DSK,Info) ;

if Disk Error then if DSK=0 then

DSK := 1 (Повторяем для диска В:} else

DSK := 2 (Закончить с ошибкой} until not Disk_Error or (DSK=2);

TrassBlock2;

if Disk_Error then

begin {Нет доступа ни к А:, ни к В:! DiskettPrepare := False;

Exit end;

(Проверяем тип дискеты} TrassBlockl;

with Info do begin

if (TracksOETracks) or

(TrackSizOETrackSiz) then begin {He эталонный тип) DiskettPrepare := False;

DSK := 3;

Exit end;

{Переустанавливаем ТПД} TrassBlockl;

GetIntVec($lE,P) ;

OldDBT := P;

New(DBT);

DBT^'OldDBT'1;

with DBT" do begin

SizeCode := SIZ;

LastSect := ETrackSiz end;

SetIntVec($lE,DBT) end;

DiskettPrepare := True end; {DiskettPrepare} /————————————;

Function LegalDiskett(var DSK: Byte): Boolean;

(Проверяет легальность мобильной копии} var

k,n: Word;

begin

(Подготавливаем дискету} if DisltettPrepare(DSK) then

begin

{Читаем ключевой сектор} TrassBlockl;

with R do begin

ah :=• 2;

al := 1;

ch :- TRK;

Cl := SEC;

dh := HED;

dl := DSK;

es := seg(Buf) ;

bx := ofs (Buf) ;

Intr($13,R) ;

SetIntVec($lE,P) ;

if (Flags and FCarry)<>0 then begin

LegalDiskett :<" False;

DSK := 4;

Exit end else

begin {Проверяем содержимое сектора} for k := 2 to 256 do

Buf[k] := Buf[k] xor Buf[l];

N := 0;

l$R-f for k := 2 to 255 do N :- N+Buf[k] ;

if (N mod 256°Buf[256]) then begin

DSK :=• 0;

LegalDiskett :- True end else begin

DSK :- 4;

LegalDiskett := False end end end end else

LegalDiskett := False end; {LegalDiskett} ^————__-——————;

Function LegalHD(var DSK: Byte): Boolean;

{Проверяет легальность стационарной копии) var

k: Word;

Date :^TDate;

Legal: Boolean;

label

ExitL;

begin {Расшифровываем ключ!

TrassBlockl;

with Key do for k := 2 to 5 do KeyW[k] :- KeyW[k] xor KeyW[l];

{Проверяем дату изготовления ПЗУ)

TrassBlock2;

k := 1;

Date := ptr($FOOO,$FFF5);

repeat

Legal :-Date"[k]=Key.Dat[k] ;

inc(k)

until not Legal or (k=5) ;

LegalHD := Legal; ,

TrassBlockl;

{Проверяем дискету)

if Legal then DSK := 0

else

Legal :- LegalDiskett(DSK) ;

LegalHD := Legal end; {LegalHD} /————————————;

Тексты программ 423

Procedure ProtCheck(var P1,P2; var Res: Integer);

{Проверяет легальность копии:

PI - адрес процедуры NORMA; P2 - адрес процедуры ALARM;

Res - результат работы:

0: был вызов NORMA;

1: был вызов ALARM;

2: не вставлена дискета.

Любое другое значение может быть только при трассировке программы}

type

РТуре = Procedure;

var

Norma: РТуре absolute Pl;

Alarm: РТуре absolute P2;

DSK : Byte;

label

L1,L2;

begin

Res :» -1;

TrassBlockl;

if Key.Hard=0 then

if LegalDiskett(DSK) then begin

TrassBlock2;

LI:

Norma;

Res := 0 end else

begin L2:

TrassBlock2;

if DSK=2 then

Res := 2 else begin Alarm;

Res := 1 end end else

if LegalHD(DSK) then

goto Ll else

goto L2 end; (ProtCheck} ^_-——————.————;

Procedure HidnSec(var Buf: TBuf; Inst,Limit: Byte);

{'Цифрует буфер ключевого сектора} var

k,n: Word;

begin

TrassBlockl;

Randomize;

for k := 2 to 254 do Buf[k] := Random (256);

Buf[l] := Random(255)+1; {Ключ для шифровки}

{$R-}

Buf[17] := Inst; {Счетчик установок} Buf[200] := Limit; {Лимит установок} n := 0; {Подсчет КС}

for k := 2 to 255 do

n := n+Buf[k] ;

Buf[256] := n mod 256; {Контрольная сумма} {Шифруем все данные} for k := 2 to 256 do

Buf[k] := Buf[k] xor Buf[l];

{$R+f end; {HidnSec} ^————————.————^

Function SetOnHD: Integer;

(Устанавливает стационарную копию на жесткий диск. Возвращает:

-1 - не вставлена дискета;

-2 - не мастер-дискета;

-3 - защита от записи или ошибка записи ГД;

-4 - программа не скопирована на ЖД;

-5 - ошибка доступа к ЖД;

-6 - исчерпан лимит установок;

-7 - программа уже установлена.

>=0 - количество оставшихся установок}

var

DSK: Byte; . '.Диск} F: file; {Файл с программой} Date^TDate; {Дата ПЗУ) NameF: String; {Имя файла с программой} W: array [1..5] of Word; {Заголовок файла} n: Word; {Счетчик} L: Longint; {Файловое смещение} Inst: Byte; {Количество установок} label ErrWrt;

begin

TrassBlockl;

if Key.HardoO then begin

SetOnHD :=-7;

Exit end;

{Проверяем резидентность программы) NameF := FExpand(ParamStr(0)) ;

if NameF[1] in ['A','B'] then begin

SetOnHD := -4;

Exit end;

(Проверяем дискету}

if not LegalDiskett(DSK) then begin

case DSK of 2: SetOnHD := -1;

else

SetOnHD := -2;

end;

Exit end;

if (Buf[200]<>255) and (Buf[17]>=Buf[200]) then

begin {Исчерпан лимит установок} SetOnHD := -6;

Exit end;

Date := ptr($FOOO,$FFF5) ;

Key.Dat := Date^;

{Шифруем параметры} Randomize;

with Key do

while Hard=0 do Hard := Random($FFFF);

for n := 2 to 5 do with Key do KeyW[n] := KeyW[n] xor Hard;

{Открываем файл с программой} TrassBlockl;

Assign(F,MameF) ;

Reset(F,1) ;

{Читаем заголовок файла} BlockRead(F,W,SizeOf(W) ,n) ;

if noSizeOf(W) then begin

SetOnHD := -5;

Exit end;

{Ищем в файле положение Hard} R.ah := $62;

MSDOS(R) ;

P := @Key;

L :- round;(DSeg-R.bx-16+W[5])*16.0)+ofs(P") ;

Seek(F,L) ;

{Записываем в файл} TrassBlockl;

BlockWrite(F,Key,SizeOf(Key),n) ;

if noSizeOf(Key) then begin

SetOnHD :» -5;

Close(F) ;

Exit end;

(Шифруем ключевой сектор} Inst :=Buf[200]-Buf[17]-l;

HidnSec(Buf,Buf[17]+l,Buf[20O]) ;

(Записываем на дискету новый ключ} TrassBlockl;

if not DiskettPrepare(DSK) then

begin {Ошибка доступа к дискете: удаляем установку} ErrWrt:

FillChar(Key,SizeOf(Key),0) ;

See)<:(F,L);

BlockWrite(F,Key,SizeOf(Key),n) ;

SetOnHD :=-3;

Close(F) ;

Exit end;

with R do begin

an =• 3 ;

al = 1;

ch = TRK;

cl = SEC;

dh - HED;

dl = DSK;

es = seg (Buf) ;

bx := ofs (Buf) ;

Intr($13,R) ;

if (Flags and FCarry)<>0 then

goto ErrWrt end;

{Нормальное завершение} SetOnHD := Inst;

SetIntVec($lE,P) ;

Close(F) end; {SetOnHD} ^———————__——;

Function RemoveFromHD: Integer; ' (Удаляет стационарную копию. Возвращает:

-1 - не вставлена дискета;

-2 - не мастер-дискета;

-3 - защита от записи или ошибка записи ГД;

-4 - программа не скопирована на ЖД;

-5 - ошибка доступа к ЖД;

>=0 - количество оставшихся установок} var

k,n: Integer;

NameF: String;

В: array [1..512] of Byte;

F: file;

DSK,Inst: Byte;

begin

TrassBlockl;

if Key.Hard=0 then begin

RemoveFromHD := -4;

Exit end;

if not LegalDiskett(DSK) then begin

if DSK=2 then

RemoveFromHD := -1 else RemoveFromHD := -2;

Exit end;

{Стираем файл с программой на ЖД} NameF := FExpand(ParamStr(0); ;

if NameF[1] in ['А'..'В'] then begin

RemoveFromHD := -4;

Exit end;

Assign(F,NameF);

Ifl-t Reset(F,I» ;

{$!+} if IOResult<>0 then begin

RemoveFromHD :" -5;

Exit end;

{Уничтожаем заголовок файла} FillChar(B,512,0) ;

BlcckWrite(F,B,51z,n) ;

if п<>512 then begin

RemoveFromHD :•= -5;

Exit end;

Close(F) ;

Erase(F); {Стереть файл! {Шифруем ключевой сектор} Inst := Buf[200]-Buf[17]+l;

HidnSec(Buf,Buf[17]-l,Buf[2OO] ) ;

{Записываем на дискету новый ключ) TrassBlockl;

if not DiskettPrepare(DSK) then begin

RertioveFromHD :~ -1;

Exit end;

with R do begin

ah = 3;

al = 1;

ch = TRK;

cl = SEC;

dh = HED;

dl = DSK;

es = seg(Buf) ;

bx = ofs (Buf) ;

Intr($13,R);

if (Flags and FCarry)<>0 then

RemoveFromHD :" ~3 else

RemoveFromHd :•' Inst end;

end; (RemoveFromHD)

 

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz