TURBO PASCAL |
Новости
|
П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) |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |