Смекни!
smekni.com

Защита программы от нелегального копирования (стр. 4 из 7)

3. Расторгуев С.П., Дмитриевский Н.Н. Искусство защиты и «раздевания» программ. – М.: Совмаркет, 1991. – 94с.

4. Фролов А.В., Фролов Г.В. Аппаратное обеспечение IBM PC: В 2-х ч. Ч. 1. – М.: «ДИАЛОГ – МИФИ». 1992. – 208с.

5. Фролов А.В., Фролов Г.В. Аппаратное обеспечение IBM PC: В 2-х ч. Ч. 2. – М.: «ДИАЛОГ – МИФИ». 1992. – 208с.


ПРИЛОЖЕНИЕ

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

1 Текст модуля F_Disk

2 Текст модуля F_Prot

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

4 Текст программы Test.exe

1 ТЕКСТ МОДУЛЯ F_DISK


{===================} UNIT F_Disk; {=====================}

{

+-------------------------------------------------------------+

| Модуль содержит подпрограммы для гибкой работы с дисками. |

| Во всех подпрограммах параметр DISK относится к логическим |

| дискам: 0=А, 1=В, 2=С, 3=D и т. д. Параметр SEC - относи- |

| тельный номер сектора; 0 = загрузочный сектор, далее по |

| секторам до конца дорожки, по головкам, по цилиндрам. |

+-------------------------------------------------------------+

}

INTERFACE

type

{Информация из BPD загрузочного сектора:}

BPB_Type=record

SectSiz: Word; {Количество байт в секторе}

ClustSiz: Byte; {Количество секторов в кластере}

ResSecs: Word; {Количество секторов перед FAT}

FatCnt: Byte; {Количество FAT}

RootSiz:Word; {Количество элементов корневого каталога}

TotSecs:Word; {Количество секторов на диске}

Media:Byte; {Дескриптор носителя}

FatSize:Word {Количество секторов в FAT}

end; {BPB_Type}

{Доплнительная информация из загрузочного сектора:}

Add_BPB_Type=record

TrkSecs:Word; {Количество секторов на дорожке

для разделов меньше 32 Мбайт или 0}

HeadCnt:Word; {Количество головок}

HidnSecLo:Word; {Количество спрятанных секторов для

разделов меньше 32 Мбайт}

HidnSecHi:Word; {Вместе с HidnSecLo дает количество

спрятанных секторов для разделов больше 32 Мбайт}

LargSectors:LongInt; {Общее количество секторов для

разделов больше 32 Мбайт}

end; {Add_BPB_Type}

{Элементдисковогокаталога:}

Dir_Type=record case Byte of

1:(

Name:array[1..8] of Char; {Имяфайлаиликаталога}

Ext:array[1..3] of Char; {Расширение}

FAttr:Byte; {Атрибутыфайла}

Reserv:array[1..10] of Byte; {Резервноеполе}

Time:Word; {Время создания}

Date:Word; {Дата создания}

FirstC:Word; {Номер первого кластера}

Size:LongInt {Размер файла в байтах});

2:(NameExt:array[1..11] of Char)

end; {Dir_Type}

{Описатель логического раздела}

PartType=record

Act:Boolean; {Флаг активности раздела}

BegHead:Byte; {Головка начала раздела}

BegSC:Word; {Сектор/цилиндр начала}

SysCode:Byte; {Системный код}

EndHead:Byte; {Головка конца раздела}

EndSC:Word; {Сектор/цилиндр конца}

RelSect:LongInt; {Относительный сектор начала}

FoolSiz:LongInt {Объем в секторах}

end; {PartType}

{Загрузочный сектор диска}

PBoot=^TBoot;

TBoot=record

case Byte of

0:(

a:array[1..11] of Byte;

BPB:BPB_Type;

Add:Add_BPB_Type;

c:array[1..+$1BE-(SizeOf(BPB_Type)+SizeOf(Add_BPB_Type)+11)] of Byte;

Par:array[1..4] of PartType);

1:(b:array[1..512] of Byte)

end;

{Описатель диска по структуре IOCTL}

IOCTL_Type=record

BuildBPB:Boolean; {СтроитьВРВ}

TypeDrv:Byte; {Типдиска}

Attrib:Word; {Атрибутыдиска}

Cylindrs:Word; {Числоцилиндров}

Media:Byte; {Типносителя}

BPB:BPB_Type;

Add:Add_BPB_Type;

Reserv:array[1..10] of Byte;

end;

{Описательдиска}

TDisk=record

Number:Byte; {Номердиска 0=А, ...}

TypeD:Byte; {Типдиска}

AttrD:Word; {Атрибутыдиска}

Cyls:Word; {Число цилиндров на диске}

Media:Byte; {Дескриптор носителя}

SectSize:Word; {Количество байт в секторе}

TrackSiz:Word; {Количество секторов на дорожке}

TotSecs:LongInt; {Полная длина в секторах}

Heads:Byte; {Количество головок}

Tracks:Word; {Число цилиндров на носителе}

ClusSize:Byte; {Количество секторов в кластере}

MaxClus:Word; {Максимальный номер кластера}

FATLock:Word; {Номер 1-го сектора FAT}

FATCnt:Byte; {Количество FAT}

FATSize:Word; {Длина FAT в секторах}

FAT16:Boolean; {Признак 16-битового элемента FAT}

RootLock:Word; {Начало корневого каталога}

RootSize:Word; {Количество элементов каталога}

DataLock:Word; {Начальный сектор данных}

end;

{Список описателей диска}

PListDisk=^TListDisk;

TListDisk=record

DiskInfo:TDisk;

NextDisk:PListDisk

end;

var

Disk_Error:Boolean; {Флагошибки}

Disk_Status:Word; {Кодошибки}

const

Disks:PListDisk=NIL; {Начало списка описателей диска}

function ChangeDiskette(Disk:Byte):Boolean;

{Возвращает TRUE, если изменялось положение

запора на указанном проиводе гибкого диска}

procedure FreeListDisk(var List: PListDisk);

{Удаляетсписокописателейдисков}

procedure GetAbsSector(Disk,Head:Byte; CSec:Word; var Buf);

{Читает абсолютный дисковый сектор с помощью прерывания $13}

function GetCluster(Disk:Byte; Sector:Word):Word;

{Возвращает номер кластера по заданному номеру сектора}

function GetDefaultDrv:Byte;

{Возвращает номер диска по умолчанию}

procedure GetDirItem(FileName:String; var Item:Dir_Type);

{Возвращает элемент справочника для указанного файла}

procedure GetDirSector(Path:String; var Disk:Byte; var Dirs,DirSize:Word);

{Возвращает адрес сектора, в котором содержится

начало нужного каталога, или 0, если каталог не найден.

Вход:

PATH - полное имя каталога ('', если каталог текущий).

Выход:

DISK - номер диска;

DIRS - номер первого сектора каталога или 0;

DIRSIZE - размер каталога (в элементах DIR_TYPE).}

procedure GetDiskInfo(Disk:Byte; var DiskInfo:TDisk);

{Возвращает информацию о диске DISK}

function GetDiskNumber(c:Char):Byte;

{Преобразует имя диска A...Z в номер 0...26.

Если указано недействительное имя, возвращает 255}

function GetFATItem(Disk:Byte;Item:Word):Word;

{Возвращает содержимое указанного элемента FAT}

procedure GetIOCTLInfo(Disk:Byte; var IO:IOCTL_Type);

{Получить информацию об устройстве согласно общему выову IOCTL}

procedure GetListDisk(var List:PListDisk);

{Формируетсписокописателейдисков}

procedure GetMasterBoot(var Buf);

{Возвращает в переменную Buf главный загрузочный сектор}

function GetMaxDrv:Byte;

{Возвращает количество логических дисков}

function Getsector(Disk:Byte;Cluster:Word):Word;

{Преобразует номер кластера в номер сектора}

function PackCylSec(Cyl,Sec:Word):Word;

{Упаковывает цилиндр и сектор в одно слово для прерывания $13}

procedure ReadSector(Disk:Byte;Sec:LongInt;NSec:Word;var Buf);

{Читает сектор(секторы) на указанном диске}

procedure SetAbsSector(Disk,Head:Byte;CSec:Word;var Buf);

{Записывает абсолютный дисковый сектор с помощью прерывания $13}

procedure SetDefaultDrv(Disk:Byte);

{Устанавливает диск по умолчанию}

procedure SetFATItem(Disk:Byte;Cluster,Item:Word);

{Устанавливает содержимое ITEM в элемент CLUSTER таблицы FAT}

procedure SetMasterBoot(var Buf);

{Записывает в главный загрузочный сектор содержимое Buf}

procedure UnPackCylSec(CSec:Word;var Cyl,Sec:Word);

{Декодирует цилиндр и сектор для прерывания $13}

procedure WriteSector(Disk:Byte;Sec:LongInt;NSec:Word;var Buf);

{Записывает сектор(секторы) на указанный диск}

IMPLEMENTATION

uses DOS;

var

Reg:Registers;

procedure Output;

{Формируетзначения Disk_Status и Disk_Error}

begin

with Reg do

begin

Disk_Error:=Flags and FCarry=1;

Disk_Status:=ax

end

end; {Output}

{----------------------}

function ChangeDiskette(Disk:Byte):Boolean;

{Возвращает TRUE, если изменялось положение

запора на указанном приводе гибкого диска}

begin

with Reg do

begin

AH:=$16;

DL:=Disk;

Intr($13,Reg);

Output;

ChangeDiskette:=Disk_Error and (AH=6)

end

end; {ChangeDiskette}

{----------------------}

procedure FreeListDisk(var List:PListDisk);

{Удаляет список дисковых описателей}

var

P:PListDisk;

begin

while List<>NIL do

begin

P:=List^.NextDisk;

Dispose(List);

List:=P

end

end; {FreeListDisk}

{---------------------}

procedure GetAbsSector(Disk,Head:Byte;CSec:Word;var Buf);

{Читает абсолютный дисковый сектор с помощью прерывания $13}

begin

with Reg do

begin

ah:=2; {Операциячтения}

dl:=Disk; {Номер привода}

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

cx:=CSec; {Цилиндр/сектор}

al:=1; {Читать один сектор}

es:=seg(Buf);

bx:=ofs(Buf);

Intr($13,Reg);

Output

end

end; {GetAbsSector}

{--------------------}

function GetCluster(Disk:Byte;Sector:Word):Word;

{Возвращает номер кластера по заданному номеру сектора}

var

DI:TDisk;

begin

GetDiskInfo(Disk,DI);

if not Disk_Error then with DI do

if(Sector-DataLock>=0) and (TotSecs-Sector>=0) then

GetCluster:= {Нормальноеобращение}

(Sector-DataLock) div ClusSize+2

else

GetCluster:=0 {Неверный номер сектора}

else GetCluster:=0 {Неверный номер диска}

end; {GetCluster}

{----------------------}

function GetDefaultDrv:Byte;

{Возвращает номер диска по умолчанию}

begin

with Reg do

begin

AH:=$19;

MSDOS(Reg);

GetDefaultDrv:=AL

end

end; {GetDefaultDrv}

{---------------------}

procedure GetDirItem(FileName:String;var Item:Dir_Type);

{Возвращает элемент справочника для указанного файла}

var

Dir:array[1..16] of Dir_Type; {Буферна 1 секторкаталога}

Path:DirStr; {Маршрутпоиска}

NameF:NameStr; {Имяфайла}

Ext:ExtStr; {Расширениефайла}

Disk:Byte; {Номердиска}

Dirs:Word; {Номерсектора}

DirSize:Word; {Размеркаталога}

Find:Boolean; {Флагпоиска}

j:Integer; {Номерэлементакаталога}

{-----------}

procedure FindItem;

{Ищет нужный элемент в секторах каталога}

var

k,i:Integer;

m:array[1..11] of char; {Массивимени}

Clus:word; {Номеркластера}

DI:TDisk;

begin

GetDiskInfo(Disk,DI); {Получаем длину кластера}

ReadSector(Disk,Dirs,1,Dir); {Читаемпервыйсектор}

k:=0; {Количество просмотренных элементов}

j:=1; {Текущий элемент каталога}

{Готовим имя и расширение для поиска}

FillChar(m,11,' ');

Move(NameF[1],m[1],Length(NameF));

if ext<>'' then

Move(Ext[2],m[9],Length(ext)-1);

Find:=False;

{Циклпоиска}

repeat

if Dir[j].Name[1]=#0 then

exit; {Обнаруженконецпоиска}

if (Dir[j].FAttr and $18)=0 then

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

Find:=True;

i:=1;

While Find and (i<=11) do

begin

Find:=m[i]=Dir[j].NameExt[i];

inc(i)

end;

end;

if not Find then inc(j);

if j=17 then

begin

inc(k,16);

if k>=DirSize then

exit; {Дошли до конца каталога}

j:=1; {Продолжаем с первого элемента следующего сектора}

if (k div 16) mod DI.ClusSize=0 then

if succ(Dirs)<DI.DataLock then

inc(Dirs) {Корневойкаталог}

else

begin {Конецкластера}

{Новыйкластер}

Clus:=GetFATItem(Disk,GetCluster(Disk,Dirs));

{Новыйсектор}

Dirs:=GetSector(Disk,Clus)

end

else {Очередной сектор - в кластере}

inc(Dirs);

ReadSector(Disk,Dirs,1,Dir)

end

until Find

end; {FindItem}

{---------}

begin {GetDirItem}

{Готовимимяфайла}

FileName:=FExpand(FileName);

FSplit(FileName,Path,NameF,Ext);

{Искатькаталог}

GetDirSector(Path,Disk,Dirs,DirSize);

Find:=Dirs<>0; {Dirs=0 - ошибкавмаршруте}

if Find then

FindItem; {Ищемнужныйэлемент}

if Find then

begin

{Переносимэлементкаталогав Item}

Move(Dir[j],Item,SizeOf(Dir_Type));

{Сброситьошибку}

Disk_Error:=False

end

else

begin {Файл не найден}

Disk_Error:=True;

Disk_Status:=$FFFF

end

end; {GetDirItem}

{------------------------}

Procedure GetDirSector(Path:String;var Disk:Byte;var Dirs,DirSize:Word);

{Возвращает адрес сектора, в котором содержится начало

нужного каталога, или 0, если каталог не найден.

Вход:

PATH - полное имя каталога ('', если каталог - текущий).

Выход:

DISK - номер диска;

DIRS - номер первого сектора каталога или 0;

DIRSIZE - размер каталога (в элементах DIR_TYPE).}

var

i,j,k:Integer; {Вспомогательные переменные}

Find:Boolean; {Признак поиска}

m:array[1..11] of Char; {Массив имени каталога}

s:string; {Вспомогательная переменная}