Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
защита программ.doc
Скачиваний:
6
Добавлен:
29.08.2019
Размер:
301.06 Кб
Скачать

Список кластеров, распределенных файлу

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

К сожалению, непосредственное чтение диска - единственная документированная возможность получения списка кластеров, распределенных файлу.

Мы рассмотрим более простой, но увы, недокументированный способ получения списка кластеров, использующий таблицу открытых файлов. Эта таблица была описана в предыдущем томе "Библиотеки системного программиста" в главе, посвященной векторной таблице связи.

Напомним, что для каждого открытого файла эта таблица содержит, кроме всего прочего, номер первого кластера, распределенного файлу, и номер кластера файла, к которому только что выполнялось обращение - last_clu.

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

Размер кластера можно получить из BPB , который находится в загрузочной записи диска.

Программа clustlst

Приведем исходный текст программы CLUSTLST (листинг 5.6). Эта программа выводит на экран содержимое таблицы файлов и список кластеров для файла, полный путь которого передается программе в качестве параметра.

Листинг 5.6. Файл clustlst\clustlst.cpp

#include <dos.h>

#include <bios.h>

#include <alloc.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <io.h>

#include <ctype.h>

typedef struct _DFCB_

{

unsigned handl_num;

unsigned char access_mode;

unsigned reserv1;

unsigned dev_info;

void far *driver;

unsigned first_clu;

unsigned time;

unsigned date;

unsigned long fl_size;

unsigned long offset;

unsigned reserv2;

unsigned reserv7;

unsigned reserv3;

char reserv4;

char filename[11];

char reserv5[6];

unsigned ownr_psp;

unsigned reserv6;

unsigned last_clu;

char reserv8[4];

} DFCB;

typedef DFCB far* LPDFCB;

typedef struct _DFT_

{

struct _DFT_ far *next;

unsigned file_count;

DFCB dfcb;

} SFT;

typedef SFT far* LPSFT;

typedef struct

{

unsigned mcb_seg;

void far *dev_cb;

void far *file_tab;

void far *clock_dr;

void far *con_dr;

unsigned max_btbl;

void far *disk_buf;

void far *drv_info;

void far *fcb_tabl;

unsigned fcb_size;

unsigned char num_bdev;

unsigned char lastdriv;

} CVT;

typedef CVT far* LPCVT;

typedef struct _EBPB_

{

unsigned sectsize;

char clustsize;

unsigned ressecs;

char fatcnt;

unsigned rootsize;

unsigned totsecs;

char media;

unsigned fatsize;

unsigned seccnt;

unsigned headcnt;

unsigned hiddensec_low;

unsigned hiddensec_hi;

unsigned long drvsecs;

} EBPB;

typedef struct _BOOT_

{

char jmp[3];

char oem[8];

EBPB bpb;

char drive;

char reserved;

char signature;

unsigned volser_lo;

unsigned volser_hi;

char label[11];

char fat_format[8];

char boot_code[450];

} BOOT;

LPSFT get_fsft(LPCVT cvt);

LPSFT get_nsft(LPSFT sft);

void show(DFCB far *);

int getboot(BOOT far *boot, int drive);

union REGS regs;

struct SREGS sregs;

int main(int argc, char *argv[])

{

CVT far *cvt;

SFT far *sft;

unsigned i,j,k;

DFCB far *dfcb, far *file_dfcb;

int handle, flag, disk;

BOOT far *boot_rec;

int status;

char *buf;

char drive[128], dir[128];

char fname[20], ext[10];

char name[12];

printf("Информация об открытых файлах DOS, "

"Frolov A., (C) 1995\n");

// Открываем файл, для которого будем

// получать список кластеров

handle = open(argv[1], O_BINARY );

if(handle == 0)

{

printf("Ошибка при открытии файла\n");

return(-1);

}

// Разбиваем путь к файлу на компоненты:

// - диск;

// - каталог;

// - имя файла;

// - расширение имени

_splitpath(argv[1], drive, dir, fname, ext);

if(drive[0] == '\0' || dir[0] == '\0' || argc < 2)

{

printf("\nУкажите полный путь к файлу\n");

return(-1);

}

printf("Исследуем расположение файла '%s'",

argv[1]);

// Комбинируем строку из имени и расширения

strcpy(name, fname);

for(i = 0; i < 8; i++)

{

if(name[i] == 0) break;

}

for(; i < 8; i++) name[i] = ' ';

name[8] = 0;

strcat(name, &ext[1]);

for(i = 8; i < 12; i++)

{

if(name[i] == 0) break;

}

for(; i < 12; i++) name[i] = ' ';

name[12] = 0;

// Преобразуем строку имени в заглавные буквы

strupr(name);

// Вычисляем номер диска

drive[0] = toupper(drive[0]);

disk = drive[0] - 'A';

// Получаем адрес векторной таблицы связи

regs.h.ah = 0x52;

intdosx(&regs, &regs, &sregs);

// Передвигаем указатель на поле msb_seg

cvt = (LPCVT)MK_FP(sregs.es, regs.x.bx - 2);

// Адрес начала таблицы файлов

sft = get_fsft(cvt);

// Сбрасываем флаг поиска файла

flag = 0;

for(;;)

{

// Конец таблицы файлов

if(sft == (SFT far *)NULL) break;

i = sft->file_count;

for(j=0;j<i;j++)

{

dfcb = (&(sft->dfcb)) + j;

// Ищем файл в таблице открытых файлов

k = _fmemcmp((const void far*)name,

(const void far*)dfcb->filename, 11);

if(k == 0)

{

printf("\nDFCB файла: "

" %Fp", dfcb);

// Запоминаем адрес таблицы

// для найденного файла

file_dfcb = dfcb;

// Показываем содержимое таблицы

show(file_dfcb);

flag = 1;

break;

}

}

if(flag == 1) break;

sft = get_nsft(sft);

}

if(flag == 0)

{

printf("Файл не найден");

close (handle);

return(-1);

}

// Заказываем буфер для чтения загрузочной записи

boot_rec = (BOOT far*)farmalloc(sizeof(*boot_rec));

if(boot_rec == NULL)

{

printf("Мало памяти");

close (handle);

return(-1);

}

// Читаем загрузочную запись в буфер

status = getboot((BOOT far*)boot_rec, disk);

// Вычисляем размер кластера в байтах

i = boot_rec->bpb.clustsize * boot_rec->bpb.sectsize;

printf("Размер кластера, байт : %d",i);

// Если произошла ошибка (например, неправильно указано

// обозначение диска), завершаем работу программы

if(status)

{

printf("\nОшибка при чтении загрузочного сектора");

close (handle);

return(-1);

}

buf = (char*)malloc(i);

if(buf == NULL)

{

printf("Мало памяти");

close (handle);

return(-1);

}

printf("\nСписок кластеров файла:\n");

// Читаем файл по кластерам, выводим номер

// последнего прочитанного кластера, который

// берем из таблицы файлов

for(;;)

{

read (handle, buf, i);

if(eof(handle)) break;

printf("%u ",file_dfcb->last_clu);

}

close (handle);

farfree(boot_rec);

free(buf);

return(0);

}

// Функция для отображения содержимого таблицы файлов

void show(DFCB far *dfcb)

{

int k;

printf("\nИмя файла: ");

for(k = 0; k < 11; k++)

{

putchar(dfcb->filename[k]);

}

printf("\nКоличество идентификаторов: %d\n"

"Режим доступа: %d\n"

"Поле reserv1: %04X\n"

"Информация об устройстве: %04X\n"

"Адрес драйвера: %Fp\n"

"Начальный кластер: %u\n"

"Время: %04X\n"

"Дата: %04X\n"

"Размер файла в байтах: %ld\n"

"Текущее смещение в файле: %ld\n"

"Поле reserv2: %04X\n"

"Последний прочитанный кластер: %u\n"

"Сегмент PSP владельца файла: %04X\n"

"Поле reserv7: %u\n",

dfcb->handl_num, dfcb->access_mode,

dfcb->reserv1, dfcb->dev_info,

dfcb->driver, dfcb->first_clu,

dfcb->time, dfcb->date, dfcb->fl_size,

dfcb->offset, dfcb->reserv2, dfcb->last_clu,

dfcb->ownr_psp, dfcb->reserv7);

}

LPSFT get_nsft(LPSFT sft)

{

LPSFT sft_next;

sft_next = sft->next;

if(FP_OFF(sft_next) == 0xffff)

return((LPSFT)NULL);

return(sft_next);

}

LPSFT get_fsft(LPCVT cvt)

{

LPSFT sft;

sft = (LPSFT)cvt->file_tab;

return(sft);

}

int getboot(BOOT far *boot, int drive)

{

struct

{

unsigned long first_sect;

unsigned nsect;

void far* buf;

} cb;

cb.first_sect = 0;

cb.nsect = 1;

cb.buf = (void far*)boot;

_BX = FP_OFF(&cb);

_DS = FP_SEG(&cb);

_CX = 0xffff;

_DX = 0;

_AX = drive;

asm int 25h

asm pop ax

asm jc err

return 0;

err:

return 1;

}

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