- •Глава V методы защиты от исследования программ
- •Средства исследования программ
- •Защита программ от дисассемблирования
- •Защита программ от работы под контролем отладчика
- •5. Защита программ от несанкционированного копирования
- •5.1. Защита дискет от копирования
- •Программа fmt256
- •Программа fmt81trk
- •Программа rw81trk
- •Программа fmtintrl
- •Программа chkintrl
- •5.2. Защита программ на жестком диске
- •Список кластеров, распределенных файлу
- •Программа clustlst
- •Привязка к bios
- •Программа biosver
- •5.3. Защита программ от трассировки
Программа rw81trk
Для записи и последующего чтения информации на дополнительную дорожку, созданную предыдущей программой, можно использовать программу RW81TRK (листинг 5.3).
Листинг 5.3. Файл fmt81trk\fmt81trk.cpp
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
typedef struct _DPB_WR_
{
char spec;
unsigned head;
unsigned track;
unsigned sector;
unsigned sectcnt;
void _far *buffer;
} DPB_WR;
char buf[1000];
char buf1[80];
int main(void)
{
union REGS reg;
struct SREGS segreg;
DPB_WR far *dbp_wr;
int sectors, i;
// Заказываем память для блока параметров
// устройства,который будет
// использован для чтения и записи
dbp_wr = (DPB_WR far*)farmalloc(sizeof(DPB_WR));
if(dbp_wr == NULL)
{
printf("\nМало памяти");
return(-1);
}
// Записываем информацию в нестандартный сектор
printf("\nВведите строку для записи "
"в нестандартный сектор,"
"\nдлина строки не должна превышать 80 байт"
"\n->");
gets(buf1);
strcpy(buf,buf1);
// Заполняем блок параметров для выполнения
// операции записи
dbp_wr->spec = 0;
dbp_wr->head = 0;
dbp_wr->track = 81;
dbp_wr->sector = 0;
dbp_wr->sectcnt = 1;
dbp_wr->buffer = buf;
// Выполняем операцию записи
reg.x.ax = 0x440d;
reg.h.bl = 1;
reg.x.cx = 0x0841;
reg.x.dx = FP_OFF(dbp_wr);
segreg.ds = FP_SEG(dbp_wr);
intdosx(®, ®, &segreg);
if(reg.x.cflag != 0)
{
printf("\nОшибка при записи: %d", reg.x.ax);
return(-1);
}
// Заполняем блок параметров для выполнения
// операции чтения
dbp_wr->spec = 0;
dbp_wr->head = 0;
dbp_wr->track = 81;
dbp_wr->sector = 0;
dbp_wr->sectcnt = 1;
dbp_wr->buffer = buf;
// Выполняем операцию чтения дорожки
reg.x.ax = 0x440d;
reg.h.bl = 1;
reg.x.cx = 0x0861;
reg.x.dx = FP_OFF(dbp_wr);
segreg.ds = FP_SEG(dbp_wr);
intdosx(®, ®, &segreg);
if(reg.x.cflag != 0)
{
printf("\nОшибка при чтении: %d",reg.x.ax);
return(-1);
}
printf("\nПрочитано из нестандартного "
"сектора:\n%s\n", buf);
// Освобождаем память
farfree(dbp_wr);
return(0);
}
Программа fmtintrl
Более интересный способ защиты дискет от копирования связан с использованием при форматировании нестандартного чередования секторов на дорожке. В программе FMTINTRL (листинг 5.4) использовано "обратное" расположение секторов - вначале идет сектор с номером 15, затем 14 и т. д.
Листинг 5.4. Файл fmtintrl\fmtintrl.cpp
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
#include <bios.h>
// Номер форматируемой дорожки
#define TRK 20
// Код размера сектора - 512 байт
#define SEC_SIZE 2
typedef struct _DPT _
{
unsigned char srt_hut;
unsigned char dma_hlt;
unsigned char motor_w;
unsigned char sec_size;
unsigned char eot;
unsigned char gap_rw;
unsigned char dtl;
unsigned char gap_f;
unsigned char fill_char;
unsigned char hst;
unsigned char mot_start;
} DPT ;
DPT far *get_dpt(void);
union REGS inregs, outregs;
char diskbuf[512];
int main(void)
{
struct diskinfo_t di;
unsigned status;
unsigned char old_sec_size,
old_fill_char, old_eot;
int i, j;
DPT far *dpt_ptr;
printf("\nПрограмма уничтожит содержимое"
"\n20-й дорожки диска А:."
"\nЖелаете продолжить? (Y,N)\n");
i = getch();
if((i != 'y') && (i != 'Y'))
return(-1);
// Получаем адрес таблицы параметров дискеты
dpt_ptr = get_dpt();
// Сохраняем старые значения из таблицы параметров
old_sec_size = dpt_ptr->sec_size;
old_fill_char = dpt_ptr->fill_char;
old_eot = dpt_ptr->eot;
// Устанавливаем в таблице параметров дискеты
// код размера сектора, символ заполнения при
// форматировании, количество секторов на дорожке
dpt_ptr->sec_size = SEC_SIZE;
dpt_ptr->fill_char = 0xf6;
dpt_ptr->eot = 18;
// Устанавливаем тип диска
inregs.h.ah = 0x17;
inregs.h.al = 3;
inregs.h.dl = 0;
int86(0x13, &inregs, &outregs);
// Устанавливаем среду для форматирования
inregs.h.ah = 0x18;
inregs.h.ch = TRK;
inregs.h.cl = dpt_ptr->eot;
inregs.h.dl = 0;
int86(0x13, &inregs, &outregs);
// Подготавливаем параметры
// для функции форматирования
di.drive = 0;
di.head = 0;
di.track = TRK;
di.sector = 1;
di.nsectors = 18;
di.buffer = diskbuf;
// Подготавливаем буфер формата для 18 секторов
// Используем обратный порядок расположения секторов
// на дорожке
for(i=0, j=18; j>0; i += 4, j--)
{
diskbuf[i] = TRK;
diskbuf[i+1] = 0;
diskbuf[i+2] = j;
diskbuf[i+3] = SEC_SIZE;
}
// Вызываем функцию форматирования дорожки
status = _bios_disk (_DISK_FORMAT , &di) >> 8;
printf("\nФорматирование завершилось с кодом: %d",
status);
// Восстанавливаем старые значения в
// таблице параметров дискеты
dpt_ptr->sec_size = old_sec_size;
dpt_ptr->fill_char = old_fill_char;
dpt_ptr->eot = old_eot;
return(0);
}
/**
* get_dpt
*
* Вычислить адрес таблицы параметров дискеты
*
* Функция возвращает указатель на таблицу
* параметров дискеты
*
**/
DPT far *get_dpt(void)
{
void far * far *ptr;
ptr = (void far * far *)MK_FP(0x0, 0x78);
return(DPT far*)(*ptr);
}