Программа 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(®s, ®s, &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; }
Получив список кластеров, распределенных защищаемому файлу, вы можете зашифровать его и записать, например, в конец защищаемого файла. Впоследствии, перед началом работы, защищенная программа может проверить свое расположение на диске и сравнить его с записанным в зашифрованном списке.