Глава – 16
РАЗРАБОТКА БОЛЬШЕГО КОЛИЧЕСТВА УТИЛИТ ДЛЯ ДИСКОВ
Введение
В этой главе мы обсудим, как использовать информацию MBR, DBR, FAT и корневых каталогов для разработки служебных программ, которые могут помочь нам в управлении данными, оптимизации хранилища или в решении многих задач по устранению неполадок на диске.
Обычно эти программы являются решением какой-то конкретной проблемы. Некоторые утилиты и их программирование были рассмотрены в этой главе.
Скрытие разделов
Обычно утилита скрытия разделов используется теми пользователями, которые работают на той компьютерной системе, которая используется пользователями. Если на одном компьютере много пользователей, то существует большая вероятность того, что данные другого пользователя могут быть прочитаны, украдены или удалены.
В таком случае, если у пользователя имеются некоторые важные данные или конфиденциальная информация на том же компьютере, он может захотеть скрыть раздел, в котором находятся его данные, таким образом, чтобы к разделу не имела доступа операционная система, а значит, к нему не мог получить доступ другой пользователь.
Когда пользователь хочет поработать в системе, он может получить доступ к разделу обратно, просто открыв раздел. Обычно такие события происходят в профессиональных учреждениях, где компьютеры используются многими студентами, но студенты старших курсов всегда беспокоятся о своих важных данных или проектной работе. Как и при отсутствии знаний, новый студент может повредить или даже удалить свои данные.
Как раздел становится скрытым
В следующей таблице представлен формат раздела в таблице разделов MBR:
Компенсировать |
Значение |
Размер |
Описание |
00H |
Байт индикатора типа загрузки |
1 байт |
Если байт равен 00H, раздел неактивен, а если байт равен 80H , раздел активен (или загрузочный). |
01H |
Начальный номер раздела |
1 байт |
Начальный номер раздела в шестнадцатеричной системе |
02H |
Номер сектора и цилиндра начала раздела |
2 байта |
6 бит первого байта составляют начальный номер сектора, а комбинация оставшихся 2 бит (как двух старших битов) и 8 бит другого байта (остальные 8 младших битов 10-битного номера) составляют начальный номер цилиндра раздела. |
04H |
Индикатор файловой системы Байт |
1 байт |
Байт индикатора файловой системы в шестнадцатеричной системе (полный список байтов индикатора раздела см. в главе «Логический подход к дискам и ОС», обсуждавшейся ранее в этой книге) |
05H |
Номер заголовка конца раздела |
1 байт |
Конечный номер раздела в шестнадцатеричной системе |
06H |
Номер сектора и цилиндра в конце раздела |
2 байта |
6 бит первого байта составляют конечный номер сектора, а комбинация оставшихся 2 бит (как двух старших битов) и 8 бит другого байта (остальные 8 младших битов 10-битного номера) составляют конечный номер цилиндра раздела. |
08H |
Абсолютный номер сектора начала раздела |
4 байта |
Количество секторов между MBR и первым сектором в разделе |
0Ч |
Абсолютный номер сектора конца раздела |
4 байта |
Количество секторов в разделе |
|
|
Всего = 16 байт |
|
В смещении 04H, в каждой записи раздела, есть байт-индикатор файловой системы. Этот байт-индикатор представляет тип файловой системы этого раздела. Если значение этого байта изменяется, изменяется идентификация раздела.
Например, значение байта индикатора раздела для «DOS 12-Bit FAT» равно 0x01. Если это значение изменить на 0x11, идентификатор файловой системы в записи таблицы разделов изменится на «Hidden DOS 12-Bit FAT» (полный список байтов индикатора раздела см. в главе «Логический подход к дискам и ОС», обсуждавшейся ранее в этой книге).
В таблице ниже приведены еще несколько примеров байта-индикатора файловой системы для некоторых типов разделов:
Индикатор типа раздела Байт |
Описание файловой системы раздела |
0x01 |
DOS 12–бит FAT |
0x11 |
Скрытый DOS 12–бит FAT |
0x04 |
DOS 16–бит FAT (<=32 МБ) |
0x14 |
Скрытый DOS 16–бит FAT (<=32 МБ) |
0x05 |
DOS расширенный |
0x15 |
Скрытый DOS расширенный |
0x06 |
DOS 16–бит большой (> 32 МБ) |
0x16 |
Скрытый DOS 16–битный большой (> 32 МБ) |
0x07 |
NTFS |
0x17 |
Скрытый NTFS |
0x0B |
Windows FAT32 |
0x1Б |
Скрытый Windows FAT32 |
0x0C |
Windows FAT32 (LBA) |
0x1С |
Скрытый Windows FAT32 (LBA) |
0x0E |
Windows FAT16 (LBA) |
0x1E |
Скрытый Windows FAT16 (LBA) |
0x0F |
Окна расширенные |
0x1F |
Скрытые окна расширены |
Здесь мы видим, что соответствующий скрытый раздел для любой файловой системы находится путем добавления значения 0x10 к ее байту системного индикатора.
Although it is not the hard and fast rule for hiding the partition yet it works even for most of the file system. The reason behind it is that when we change the value of partition indicator byte, the identity of file system in the partition table entry is changed. And it is very rare that the new file system is also supported by the same operating system.
Writing program to hide partition
The program given next is used to hide the partition using the partition entry of that partition from partition table of MBR. If you want to hide other logical partitions in the extended volume you should access the extended MBRs.
The coding of the program has been given next:
/* Program to hide the partition using Partition table entry of that Partition from MBR */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
int result, tohide;
int i;
static char dbuf[512];/* Data Buffer to read-Write the
Sector information */
clrscr();
dinfo.drive = 0x80; /* drive number for First
Hard Disk */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
/* Read the First Sector of the Disk */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
printf("The Partition Codes of Four Partition Entries are,
0x%02x, 0x%02x, 0x%02x And 0x%02x.\n",
dbuf[450] & 0xff, dbuf[466] & 0xff,
dbuf[482] & 0xff, dbuf[498] & 0xff);
textcolor(15);
gotoxy(5,5);cprintf("Partition Entry in MBR is as
follows:");
gotoxy(10,7);cprintf("1. "); showtype(dbuf[450] & 0xff);
gotoxy(10,8);cprintf("2. "); showtype(dbuf[466] & 0xff);
gotoxy(10,9);cprintf("3. "); showtype(dbuf[482] & 0xff);
gotoxy(10,10);cprintf("4. "); showtype(dbuf[498] & 0xff);
/* get the User Input for Hiding the Partition */
gotoxy(1,15);
printf("Enter The partition no. you want to hide,
Or Press any other key to Exit... ");
tohide=getche();
switch(tohide)
{
case '1': /* Hide First Partition in partition Table */
dbuf[450] = dbuf[450] +16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
case '2': /* Hide second Partition in partition Table */
dbuf[466] = dbuf[466]+16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
case '3': /* Hide third Partition in partition Table */
dbuf[482] = dbuf[482] +16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
case '4': /* Hide Fourth Partition in partition Table */
dbuf[498] = dbuf[498]+16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
default:
exit(0);
}
if ((result & 0xff00) == 0)
{
printf("\n\nThe New Partition Codes of Four Partition
Entries are, 0x%02x, 0x%02x, 0x%02x And 0x%02x.\n",
dbuf[450] & 0xff, dbuf[466] & 0xff,
dbuf[482] & 0xff, dbuf[498] & 0xff);
getch();
}
else
{
printf("Cannot Change the Byte, status = 0x%02x\n",
result);
getch();
}
}
return 0;
}
Comments on coding:
The program reads file system indicator bytes of all four partition entries in partition table of MBR. The function showtype( ) is used to show the name of file system for the corresponding value of file system indicator byte.
The user selects the partition to hide from the menu displayed on the screen and then 16 (0x10) is added to the value of file system indicator byte of that partition to hide it.
The coding of the function showtype( ) is as follows:
/* Function to show the name of file system corresponding to the value of file system indicator byte */
showtype(i)
{
switch (i)
{
case 0x00 :cprintf("Empty"); break;
case 0x01 :cprintf("DOS 12-bit FAT"); break;
case 0x02 :cprintf("XENIX root"); break;
case 0x03 :cprintf("XENIX usr"); break;
case 0x04 :cprintf("DOS 16-bit <32M"); break;
case 0x05 :cprintf("Extended"); break;
case 0x06 :cprintf("DOS 16-bit >=32M"); break;
case 0x07 :cprintf("OS/2 HPFS"); break;
case 0x08 :cprintf("AIX"); break;
case 0x09 :cprintf("AIX bootable"); break;
case 0xa :cprintf("OS/2 Boot Manag"); break;
case 0xb :cprintf("Win95/98/ME FAT32"); break;
case 0xc :cprintf("Win95/98/ME FAT32 (LBA)"); break;
case 0xd :cprintf("Win95 FAT16"); break;
case 0xe :cprintf("Win95 FAT16 (LBA)"); break;
case 0xf :cprintf("Win95 Extended"); break;
case 0x11 :cprintf("Hidden FAT-12");break;
case 0x12 :cprintf("Compaq Diagnostics");break;
case 0x14 :cprintf("Hidden FAT-16 (<32)");break;
case 0x15 :cprintf("Hidden Extended");break;
case 0x16 :cprintf("Hidden FAT-16");break;
case 0x17 :cprintf("NTFS"); break;
case 0x40 :cprintf("Venix 80286"); break;
case 0x51 :cprintf("Novell?"); break;
case 0x52 :cprintf("Microport"); break;
case 0x63 :cprintf("GNU HURD"); break;
case 0x64 :
case 0x65 :cprintf("Novell Netware"); break;
case 0x75 :cprintf("PC/IX"); break;
case 0x80 :cprintf("Old MINIX"); break;
case 0x81 :cprintf("Linux/MINIX"); break;
case 0x82 :cprintf("Linux swap"); break;
case 0x83 :cprintf("Linux native"); break;
case 0x85 :cprintf("Linux Extended"); break;
case 0x93 :cprintf("Amoeba"); break;
case 0x94 :cprintf("Amoeba BBT"); break;
case 0xa5 :cprintf("BSD/386"); break;
case 0xa6 :cprintf("OpenBSD"); break;
case 0xa7 :cprintf("NEXTSTEP"); break;
case 0xb7 :cprintf("BSDI fs"); break;
case 0xb8 :cprintf("BSDI swap"); break;
case 0xc7 :cprintf("Syrinx"); break;
case 0xdb :cprintf("CP/M"); break;
case 0xe1 :cprintf("DOS access"); break;
case 0xe3 :cprintf("DOS R/O"); break;
case 0xf2 :cprintf("DOS secondary"); break;
case 0xff :cprintf("BBT"); break;
default :cprintf("UNKOWN");
}
return 0;
}
Writing program to Unhide the Partition
The program to unhide the hidden partition works just opposite to the program which hides the program. In this program we subtract 16 (0x10) from the value of file system indicator byte of the hidden partition.
The coding of the program in as follows:
/* Program to unhide the partition hidden by the previous program */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
int result, tohide;
int i;
static char dbuf[512];/* Data buffer */
clrscr();
dinfo.drive = 0x80; /* drive number for
First Hard Disk */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
printf("The Partition Codes of Four Partition
Entries are, 0x%02x, 0x%02x, 0x%02x And 0x%02x.\n",
dbuf[450] & 0xff, dbuf[466] & 0xff,
dbuf[482] & 0xff, dbuf[498] & 0xff);
textcolor(15);
gotoxy(5,5);
cprintf("Partition Entry in MBR is as follows:");
gotoxy(10,7);cprintf("1. "); showtype(dbuf[450] & 0xff);
gotoxy(10,8);cprintf("2. "); showtype(dbuf[466] & 0xff);
gotoxy(10,9);cprintf("3. "); showtype(dbuf[482] & 0xff);
gotoxy(10,10);cprintf("4. "); showtype(dbuf[498] & 0xff);
/* Get the Use input to unhide the partition */
gotoxy(1,15);printf("Enter The partition no., Which to
unhide, Or Press any other key to
Exit... ");
tohide=getche();
switch(tohide)
{
/* Unhide first partition of partition table */
case '1':
dbuf[450] = dbuf[450] -16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
/* Unhide second partition of partition table */
case '2':
dbuf[466] = dbuf[466]-16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
/* Unhide third partition of partition table */
case '3':
dbuf[482] = dbuf[482] -16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
/* Unhide fourth partition of partition table */
case '4':
dbuf[498] = dbuf[498]-16;
result = _bios_disk(_DISK_WRITE, &dinfo);
break;
default:
exit(0);
}
if ((result & 0xff00) == 0)
{
printf("\n\nThe New Partition Codes of Four Partition
Entries are, 0x%02x, 0x%02x, 0x%02x And 0x%02x.\n",
dbuf[450] & 0xff, dbuf[466] & 0xff,
dbuf[482] & 0xff, dbuf[498] & 0xff);
getch();
}
else
{
printf("Cannot Change the Byte, status = 0x%02x\n",
result);
getch();
}
}
return 0;
}
Comments on Program
Be careful while giving the partition number to unhide. If the number of partition is entered wrong by mistake, the file system information of that partition will be changed and partition may become inaccessible. However the program previously discussed to hide the partitions, may help you to cure the file system indicator byte of that partition.
Writing program to delete Partition
The program to delete partition is used for troubleshooting purpose. For example, assume that you had the FAT32 file system partitions in your disk. Now you decided to install the LINUX operating system in your disk simultaneously.
If any how, the installation of operating system is interrupted in between, at the stage when the modifications were being made to the partition table of the MBR. In such cases there are a lot of possibilities that the partition, in which you were going to install the other operating system, becomes inaccessible.
In this case the disk space of the lost partition becomes useless due to being inaccessible. However if we delete the partition information of that partition from partition table any how, we can again make this space usable using FDISK command of DOS.
The program to delete the partition entry from the partition table of MBR has been given next:
/* Program to delete the second partition entry from the partition table of MBR */
# include <bios.h>
/* structure to read the partition entry from partition table */
struct partition
{
/* Active Partition Byte */
unsigned char bootable ;
/* Starting Head */
unsigned char start_side ;
/* combination of Starting sector and cylinder number */
unsigned int start_sec_cyl ;
/* File system Indicator Byte */
unsigned char parttype ;
/* Ending Head */
unsigned char end_side ;
/* combination of Starting sector and cylinder number */
unsigned int end_sec_cyl ;
/* Relative Sector Number */
unsigned long part_beg ;
/* Partition length in sectors */
unsigned long plen ;
} ;
/* Structure to read-write MBR */
struct part
{
/* IPL (Initial Program Loader) */
unsigned char master_boot[446] ;
/* Partition table */
struct partition pt[4] ;
/* Magic Number */
int lasttwo ;
} ;
struct part p ;
void main()
{
unsigned int t1,t2;
clrscr();
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* display the information of
Partition table */
getch();
p.pt[1].bootable = 0;
p.pt[1].start_side = 0 ;
p.pt[1].start_sec_cyl = 0 ;
p.pt[1].parttype = 0;
p.pt[1].end_side = 0;
p.pt[1].end_sec_cyl = 0;
p.pt[1].part_beg = 0;
p.pt[1].plen = 0;
printf("\n\n\n After Deleting the Second Partition
Entry From MBR Partition Table,");
printf("\n The Partition Table will Be Changed as
Follows: ");
/* To Delete Second Partition Information from partition
table of MBR Remove the forward slashes from the
biosdisk( ) function. Do not use Carelessly, Partition
information of Second Partition of Partition Table will
be Erased Completely. */
////// biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) ;
display(); /* Display the information of partition
table after modification */
getch();
}
Comments on program:
Uncomment the biosdisk ( 3, 0x80, 0, 0, 1, 1, &p ) function to delete the second partition from the partition table of MBR.
To delete the partition, all the parameters of it, are set to 0 in partition table entry in MBR. Always remember that if you delete the extended partition, all the logical partitions of that extended partition will also become inaccessible.
The Function display( ) is used to display the partition table of MBR. The coding of the function is as follows:
/* Function to display partition table of MBR */
display()
{
unsigned int s_sec, s_trk, e_sec, e_trk, i, t1, t2 ;
char type[20], boot[5] ;
printf("\n\nPart. Boot Starting location Ending Location
Relative Number of");
printf("\nType Side Cylinder Sector Side Cylinder
Sector Sectors Sectors\n");
for ( i = 0 ; i <= 3 ; i++ )
{
if ( p.pt[i].bootable == 0x80 )
strcpy ( boot, "Yes" ) ;
else
strcpy ( boot, "No" ) ;
switch ( p.pt[i].parttype )
{
case 0x00 :
strcpy ( type, "Unused" ) ; break ;
case 0x1 :
strcpy ( type, "FAT12" ) ; break ;
case 0x2 :
strcpy ( type, "Xenix" ) ; break ;
case 0x3 :
strcpy ( type, "Xenix:usr" ) ; break ;
case 0x4 :
strcpy ( type, "FAT16<32M" ) ; break ;
case 0x5 :
strcpy ( type, "DOS-Ext." ) ; break ;
case 0x6 :
strcpy ( type, "FAT16>32M" ) ; break ;
case 0x7 :
strcpy ( type, "NTFS" ) ; break ;
case 0x0b :
strcpy ( type, "FAT32" ) ; break ;
case 0x0c :
strcpy ( type, "FAT32-LBA" ) ; break ;
case 0x0d :
strcpy ( type, "VFAT16" ) ; break ;
case 0x0e :
strcpy ( type, "VFAT16-LBA" ) ; break ;
case 0x0f :
strcpy ( type, "FAT EXT" ) ; break ;
case 0x17 :
strcpy ( type, "HPFS" ) ; break ;
case 0x81 :
strcpy ( type, "Old LINUX" ) ; break ;
case 0x82 :
strcpy ( type, "LinuxSwap" ) ; break ;
case 0x83 :
strcpy ( type, "LinuxNative" ) ; break ;
case 0x85 :
strcpy ( type, "Linux Ext." ) ; break ;
default :
strcpy ( type, "Unknown" ) ; break ;
}
s_sec = ( p.pt[i].start_sec_cyl & 0x3f ) ;
t1 = ( p.pt[i].start_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].start_sec_cyl & 0x00c0 ) << 2 ;
s_trk = t1 | t2 ;
e_sec = ( p.pt[i].end_sec_cyl & 0x3f ) ;
t1 = ( p.pt[i].end_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].end_sec_cyl & 0x00c0 ) << 2 ;
e_trk = t1 | t2 ;
printf ( "\n%6s %3s", type, boot ) ;
printf ( "%4d %6d %8d", p.pt[i].start_side,
s_trk,s_sec ) ;
printf ( "%7d %6u %8u", p.pt[i].end_side, e_trk,
e_sec ) ;
printf ( " %10lu %10lu", p.pt[i].part_beg,
p.pt[i].plen ) ;
}
return 0;
}
Formatting “Track 0 Bad” floppy
This program is used to format those floppies which have bad sectors on their track 0 and when are formatted with DOS or windows, display error messages like “Track 0 BAD”. However you can also use it to format normal floppies.
The coding of the program has been given in the disk included with this book with the name “TTFORMAT.C”. The working logic of the program is same as the program published in PCQUEST computer magazine, in February 2003 edition.
In this program, we try to make this type of floppies reusable by formatting them. The program sounds that you can handle the floppy disk even with some bad sectors on it. However, if the first sector of the disk is bad, the floppy can not be formatted.
The program rewrites all the DBR, FAT and Root Directory information. If there are bad sectors on the surface of the disk, they are marked as bad in FAT.
In the coding of the program, the structure BPB is used to writer the BIOS Parameter Block of the DBR. The structure boot_sector is used to write the DBR of the disk. The structure address_field is used for interacting with number of cylinder, heads, and sectors per track and with the size of the sector.
Different functions used in the coding of the program and their description have been given in the table given next.

The Volume Serial Number of the Floppy disk is calculated by the DOS according to current date and time of the system clock.
The first part of the serial number is calculated by the sum of the time (seconds and hundredths of a second) and the date (month and day). The second part of the serial number is equal to the sum of the time (hours and minutes) and date (year).
All the calculations are performed in hexadecimal system. For example, let us assume that you formatted the floppy in DOS environment at 11:16:28:65 on 10/23/2003. Now let us calculate the serial number of the disk.
The time in (seconds and Hundredths of seconds) format is
= (28 and 65)
= (1CH and 41H)
Write it as 1C41
Similarly, date in (month and day) format is
= (10 and 23)
= (0AH and 17H)
Write it as 0A17
Similarly, time in (hours and minutes) format is,
= (11 and 16)
= (0BH and 10H)
Write it as 0B10
And the year will be
= 2003
= 07D3
Now, let us calculate the serial number of the floppy disk, according to the description given before. The first part of the serial number well be (1C41 + 0A17) = 2658 and the second part of the serial number will be (0B10 + 07D3) = 12E3.
Writing the Disk Editing Tool
Кодировка программы редактирования диска была дана на диске, включенном в эту книгу, с именем файла «TTEDITOR.C». Вы можете использовать эту программу для анализа поверхности жестких дисков или дискет. Даже большую часть времени при написании этой книги я использовал TTEDITOR для анализа поверхности диска или выполнения модификаций диска.
Вот некоторые из важных задач, которые может выполнять эта программа редактирования:
- Считывание посекторной информации с поверхности жестких дисков и дискет.
- Записать резервную копию любого сектора в файл.
- Восстановите данные сектора из файла.
- Измените один байт.
- Калькулятор для преобразования шестнадцатеричных чисел в десятичные и двоичные.
Программа использует функции biosdisk( ) и _bios_disk( ) для доступа к дискам. Если вы хотите проанализировать диск за пределами 8,4 ГБ, измените программу с использованием расширений INT 13H. Описание функций, используемых в программе, приведено в следующей таблице:
Функция |
Описание |
bkground() |
создает фон и рамку первого экрана |
clsline( ) |
Используется для очистки всей строки с экрана, заданного номером строки. |
обновить( ) |
Функция вызова всех функций отображения на экране |
writetofile() |
Функция записи данных сектора в пользовательский файл. |
запись в сектор ( ) |
Функция восстановления сектора из указанного файла. |
msgdisp() |
Функция отображения сообщений на экране. |
изменить( ) |
Функция для изменения одного байта любого сектора, указанного пользователем. |
рамка( ) |
Функция рисования структуры кадра секторного дисплея |
dispmax( ) |
Отображение максимального номера CHS диска (действительно для дисков объемом до 8,4 ГБ) |
отображать( ) |
Отображение сектора и информации на экране. |
hextodec( ) |
Функция для преобразования шестнадцатеричного числа в соответствующее десятичное и двоичное число. |