章 – 14
「生ファイル」回復のためのプログラミング
Rawファイルの回復
ファイルの最初と最後に書かれた文字の特定のシーケンスまたは組み合わせを持つ多くの特定のファイルタイプがあります。これらの組み合わせは、ディスク編集プログラムを使用して簡単に分析できます。 DOSのEDITコマンドを使用して、ASCII形式のファイルの構造を調べることもできます。
ファイルの先頭にある特定の文字のシーケンスまたは組み合わせは通常ヘッダーと呼ばれ、ファイルの末尾に格納されている文字のシーケンスまたは組み合わせはファイルのフッターと呼ばれます。
データを回復するためのFATまたはルートディレクトリ情報が利用できないようなタイプのディスククラッシュでデータを失った場合は、ヘッダーとフッターを使用してこれらの特定のファイルタイプを検索できます。ヘッダーはその特定のタイプのファイルの開始を示し、フッターはその特定のファイルタイプのファイルの終了を示します。
ここでは、特定のファイルタイプのraw構造を使用してデータを回復しているため、回復手法はRaw FileRecoveryと呼ばれます。ディスクの表面は、ヘッダーとフッターの情報を見つけるためにセクターごとに検索されます。
Raw File Recoveryには幅広いアプリケーションがありますが、リカバリの特定のケースがいくつかあり、それが大いに役立つ可能性があります。たとえば、誤って重要なファイルが含まれているディスクでデータ消去プログラムを実行したが、プログラムを停止するまで、オペレーティングシステムファイルを含むMBR、DBR、FAT、およびルートディレクトリのすべての情報が消去されます。
このような場合、フォーマット回復プログラムでさえ、データの回復に役立たない場合があります。ここでは、Rawファイルリカバリを使用して、ヘッダーとフッターを検索することにより、これらの特定のファイルタイプのファイルをリカバリできます。
これだけでなく、ディスクのすべての論理パーティションを削除し、以前とは異なるサイズのパーティションを再作成し、インストールしたようなハードディスクを使用している場合でも、データを回復できます。オペレーティングシステム。
これで、ディスクをパーティション分割してフォーマットする前に、ディスクにいくつかの重要なデータがあったことを思い出すことができます。オペレーティングシステムをインストールしたばかりの場合は、ファイルが復元される可能性が高くなります。
Raw File Recoveryのパフォーマンスに影響を与える要因は、断片化されたデータと、他のデータによって上書きされたデータの量です。ただし、rawファイルの回復のためのアプリケーションの領域を自分で見つけることができます。
生ファイル回復プログラムでファイルを検索する手順またはほとんどのルールは、次の条件を考慮します。
- ディスクのセクターでファイルのヘッダーまたは複数のファイルタイプを同時に検索します。
- 任意のファイルタイプのヘッダーが見つかった場合は、データをファイルに保存し、次の4つの条件を確認してファイルを閉じて保存します
- そのファイルタイプのフッターが見つかりました
- 同じファイルタイプの別のヘッダーが見つかりました
- 別のファイルタイプのヘッダーが見つかりました
- プログラムで定義されたファイルタイプのヘッダーまたはフッターが他に見つからず、データを保存しているファイルのサイズが、プログラムでファイルサイズに定義した最大サイズ制限に達しました。
ファイルタイプのヘッダーとフッターを見つけたセクターのデータを含む情報をファイルに保存する必要があります。
いくつかの重要なファイルタイプのヘッダーとフッター
いくつかの重要なファイルタイプのヘッダーとフッターは、次に示す表に示されています。表に示されているフッターは、指定されたファイル・タイプのファイルの末尾にあるか、データをリカバリーするためのフッターとして使用できるようにファイルの末尾のオフセットにあります。
DOSのEDITコマンドを使用するか、任意のディスク編集ツールを使用して、これらのファイルタイプとは異なるヘッダーとフッターを自分で検索することもできます。わかりやすくするために、16進法を使用して情報を表現しました。
Extension |
Header (Hex) |
Footer (Hex) |
DOC |
D0 CF 11 E0 A1 B1 1A E1 |
57 6F 72 64 2E 44 6F 63 75 6D 65 6E 74 2E |
XLS |
D0 CF 11 E0 A1 B1 1A E1 |
FE FF FF FF 00 00 00 00 00 00 00 00 57 00 6F 00 72 00 6B 00 62 00 6F 00 6F 00 6B 00 |
PPT |
D0 CF 11 E0 A1 B1 1A E1 |
50 00 6F 00 77 00 65 00 72 00 50 00 6F 00 69 00 6E 00 74 00 20 00 44 00 6F 00 63 00 75 00 6D 00 65 00 6E 00 74 |
ZIP |
50 4B 03 04 14 |
50 4B 05 06 00 |
JPG |
FF D8 FF E0 00 10 4A 46 49 46 00 01 01 |
D9 (“Better To Use File size Check”) |
GIF |
47 49 46 38 39 61 4E 01 53 00 C4 |
21 00 00 3B 00 |
PDF |
25 50 44 46 2D 31 2E |
25 25 45 4F 46 |
Rawファイル回復のためのプログラムを書く
次に、Microsoft Wordファイル(.DOC拡張子)のRawファイル回復プログラムのコーディングを示します。プログラムは、ディスクのセクター内のファイルを検索し、ファイル名を自動的に作成することにより、復元されたファイルを自動的に保存します。
ファイルを保存するためにユーザーが指定したパスは、復元されたデータを保存するための宛先パスとして使用されます。宛先ディレクトリが存在しない場合、プログラムは最大1つのディレクトリレベルで宛先を作成できます。
ここに記載されているリカバリプログラムは、大容量ディスクでもデータの検索とリカバリをサポートします。プログラムは、2番目の物理ハードディスクのデータを検索するように作成されています。
/ * MicrosoftWordファイルを回復するための生のファイル回復プログラム */
#include<stdio.h>
#include<dos.h>
/* Structure to be used by getdrivegeometry function using INT 13H Extension, Function Number 0x48. */
struct geometry
{
unsigned int size ; /* (call) size of Buffer */
unsigned int flags ; /* Information Flags */
unsigned long cyl ; /* Number of Physical
Cylinders on Drive */
unsigned long heads ;/* Number of Physical
Heads on Drive */
unsigned long spt ; /* Number of Physical
Sectors Per Track */
unsigned long sectors[2] ; /* Total Number of
Sectors on Drive */
unsigned int bps ; /* Bytes Per Sector */
} ;
/* Structure of Disk Address packet format, to be used by the readabsolutesectors Function */
struct diskaddrpacket
{
char packetsize ; /* Size of Packet, generally 10H */
char reserved ; /* Reserved (0) */
int blockcount ; /* Number of Blocks to Transfer */
char far *bufferaddress ; /* address to Transfer
Buffer */
unsigned long blocknumber[2] ; /* Starting Absolute
Block Number */
} ;
/////ドライブパラメータを取得する関数\\\\\
unsigned long getdrivegeometry (int drive)
{
union REGS i, o ;
struct SREGS s ;
struct geometry g = { 26, 0, 0, 0, 0, 0, 0, 0 } ;
i.h.ah = 0x48 ; /* Function Number 0x48 */
i.h.dl = drive; /* Drive Number */
i.x.si = FP_OFF ( (void far*)&g ) ;
s.ds = FP_SEG ( (void far*)&g ) ;
/* Invoke the specified function number of INT 13H extension with Segment Register Values */
int86x ( 0x13, &i, &o, &s ) ;
printf("\n Head = %lu, Sectors Per Track = %lu, Cylinder = %lu\n",
g.heads,g.spt,g.cyl);
/* If get drive Geometry function Fails, Display Error Message and Exit */
if(g.spt==0)
{
printf("\n Get Drive Geometry Function Fails....");
printf("\n Extensions Not Supported, Press any Key to
Exit...");
getch();
exit(1);
}
return *g.sectors; /* Return The Number of
Sectors on Drive */
}
unsigned long file_size=0, i=0;
unsigned long start_file=0, end_file=0;
unsigned long Sectors_in_HDD2=0, loop=0;
char buffer[512], filename[80], temp[8];
char path[80];
unsigned int result,num=0;
/ * MicrosoftWordファイルのヘッダー */
char header[10] = {0xD0,0xCF,0x11,0xE0, 0xA1,0xB1,0x1A,0xE1};
/* Footer of Microsoft Word Files */
char DOC_footer[14] =
{0x57,0x6F,0x72,0x64, 0x2E,0x44,0x6F,0x63,
0x75,0x6D,0x65,0x6E,0x74};
/// Start Of main \\\
void main()
{
clrscr();
/* If total no. of hard disks attached is less
then two, Display Error Message and Exit. */
if(((char)peekb(0x0040, 0x0075))<2)
{
printf("\n\n You Must Have At least Two Hard Disks
Attached to your Computer To Run This");
printf("\n Program. This Program has been developed
to recover the Data of Second Hard Disk.");
printf("\n Press any Key to Exit... ");
getch();
exit(1);
}
Sectors_in_HDD2=getdrivegeometry (0x81);
printf("\n Total Sectors in second Hard Disk = %lu",
Sectors_in_HDD2);
printf("\n\n \"You must save the recovered files in
another Hard Disk, Not in the Same Disk,");
printf("\n in which you are searching the lost
data.\"");
printf("\n\n Enter The Destination Path to save the
Recovered Files...\n ");
gets(path);
/* check if destination directory exists or Not */
if(access(path, 0) != 0)
{
/* if Destination directory does not exist, create
the Directory up to one level */
if(mkdir(path)!=0)
{
printf("\n Could Not Create Directory \"%s\"",
path);
printf("\n Check Path..., Press any key to
exit...");
getch();
exit(1);
}
}
strcat(path,"\\Ptt");
/ * 画面上でカーソルを非表示(および表示)する関数 */
show_hide_cursor ( 32,
gotoxy(15,18);cprintf("[ %d ] Files Recovered...",
num);
/* search for the data until the ending sector of the disk */
while(loop<Sectors_in_HDD2)
{
/* Read one Sector (Sector No. = loop) */
readabsolutesectors ( 0x81, loop, 1, buffer );
gotoxy(19,16);cprintf("Scanning Sector Number = % ld",
loop);
if(kbhit())
{
show_hide_cursor ( 6, 7 ); /* Retrieve the
cursor before
Exit the program
*/
exit(0);
}
/* if specified header is found */
if((memcmp ( buffer, header,7))==0)
{
/* logic to provide the file name to automatically
create the files to save the recovered data */
strcpy(filename, path);
itoa(num,temp,10);
strcat(filename, temp);
strcat(filename,".DOC");
start_file=loop; /* starting sector of file */
gotoxy(5,19);cprintf("File Found..., Saving As %s",
filename);
num++;
//////////////ファイルのクローズ条件\\\\\\\\\\\\\\\\
file_size=0;
while( file_size<5000000)
{
loop++;
file_size+=512;
readabsolutesectors ( 0x81, loop, 1, buffer );
gotoxy(19,16);cprintf("Scanning Sector Number = % ld" ,
loop);
/* if file size reaches up to maximum size of 5MB */
if(file_size>=5000000)
{
end_file=loop; /* Ending Sector of File */
Recover_the_file();/* write the data to file */
break;
}
/* if footer of DOC file is found */
for(i=0;i<512;i++)
{
if( memcmp(buffer+i,DOC_footer,12)==0 )
{
end_file=loop; /* Ending Sector of File */
Recover_the_file();/* write the data to file */
break;
}
}
/* if another header is found */
if( memcmp(buffer,header,7)==0 )
{
loop=loop-1;
end_file=loop; /* Ending Sector of File */
Recover_the_file();/* write the data to file */
break;
}
if(kbhit())
{
show_hide_cursor ( 6, 7 );
exit(0);
}
}
}
loop++;
}
//////// ループはここで終了します ////////
/* display message for completion of search and recovery */ if(loop>=Sectors_in_HDD2 )
{
gotoxy(17,23);cprintf("The Saving of files in the Disk is
Completed !!");
gotoxy(17,24);cprintf("Press Any Key to Exit...");
show_hide_cursor ( 6, 7 );
getch();
}
}
構造ジオメトリは、INT 13H拡張機能、関数番号0x48を使用するgetdrivegeometry関数によって使用され、ディスクのさまざまなパラメータを取得します。
構造体diskaddrpacketは、readabsolutesectors関数で使用されるディスクアドレスパケット形式用です。
関数getdrivegeometry(int drive)は、ディスクで指定された物理ドライブ番号ドライブのドライブパラメータを取得することです。
(char)peekb(0x0040、0x0075)は、セグメント0040H:offset0075Hで表されるメモリ位置に格納されているコンピュータに接続されているハードディスクの数を見つけるために使用されます。接続されているハードディスクの総数が2つ未満の場合は、エラーメッセージを表示して終了します。
Sectors_in_HDD2 = getdrivegeometry(0x81); 2番目の物理ハードディスク(0x81)のさまざまなパラメータを検索し、ディスクのセクターの総数を返します。
ステートメントif(access(path、0)!= 0)は、ユーザーが指定したパスのアクセシビリティをチェックします。宛先ディレクトリが存在しない場合、宛先は1レベルまで作成され、条件if(mkdir(path)!= 0)によってチェックされた指定されたパスが不正である場合、エラーメッセージが表示されます。
復元されたデータを保存するために自動的に作成されたファイルのファイル名は、ファイルの最初の3文字がstrcat(path,"\\Ptt"); 関数。これは、宛先ディレクトリでファイル名が重複しないようにするために行われます。したがって、回復されたファイルのファイル名は「PTTxxxxx.DOC」の形式で与えられます
関数show_hide_cursor(32、0); show_hide_cursor(6、7);の画面からカーソルを非表示にするために使用されます。カーソルを画面に戻します。
関数readabsolutesectors(0x81、ループ、1、バッファー);セクター番号ループで指定された2番目の物理ハードディスクの1つのセクターを読み取ります。
ファイルのヘッダーが見つかった場合、start_file = loop; start_fileを、リカバリするファイルの開始セクター番号に設定します。プログラムは、ファイルの終了セクターを見つけるために、次に示す3つの条件に従います。
- ファイルサイズが最大サイズの5MBに達した場合
- DOCファイルのフッターが見つかった場合
- 別のヘッダーが見つかった場合
長整数のend_fileは、end_file = loopによってファイルの終了セクター番号に設定されます。 3つのうちの1つの条件が満たされた場合。これで、セクター番号start_fileからセクター番号end_fileまでのセクターのデータが、関数Recover_the_file()を使用してファイルに保存されます。
関数Recover_the_file()のコーディングを次に示します。
/ * セクター番号start_fileからセクター番号end_fileまでのセクターのデータを保存する関数 */
Recover_the_file()
{
FILE *fp;
if((fp=fopen(filename, "wb"))==NULL)
{
gotoxy(10,23);printf("Error Opening File %s",
filename);
getch();
exit(1);
}
for(i=start_file;i<=end_file;i++)
{
gotoxy(19,16);cprintf("Scanning Sector Number =
%ld", i);
readabsolutesectors ( 0x81, i, 1, buffer );
fwrite(buffer,512,1, fp);
}
fclose(fp);
gotoxy(15,18);cprintf("[ %d ] Files Recovered...",num);
gotoxy(5,19);cprintf(" ");
return;
}
次に、関数readabsolutesectorsのコーディングを示します。この機能は、INT13H拡張機能と機能番号42Hを使用してセクターを読み取ります。
機能の詳細については、本書で前述した「バックアップの作成」の章を参照してください。関数のコーディングは次のとおりです。
//// 絶対セクターを読み取る関数 \\\\
int readabsolutesectors ( int drive,
unsigned long sectornumber,
int numofsectors,
void *buffer )
{
union REGS i, o ;
struct SREGS s ;
struct diskaddrpacket pp ;
pp.packetsize = 16 ; /* packet size = 10H */
pp.reserved = 0 ; /* Reserved = 0 */
pp.blockcount = numofsectors ; /* Number of sectors
to read */
/* for Data buffer */
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void far*)buffer), FP_OFF((void far*)buffer));
pp.blocknumber[0] = sectornumber ; /* Sector number
to read */
pp.blocknumber[1] = 0 ; /* Block number */
i.h.ah = 0x42 ; /* Function Number*/
i.h.dl = drive ; /* Physical Drive Number */
/* ds:si for buffer Parameters */
i.x.si = FP_OFF ( (void far*)&pp ) ;
/* ds:si for buffer Parameters */
s.ds = FP_SEG ( (void far*)&pp ) ;
/* Invoke the specified Function of INT 13H with
segment register values */
int86x ( 0x13, &i, &o, &s ) ;
if ( o.x.cflag==1)
return 0 ; //failure
else
return 1 ; // success
}
次の関数は、画面上でカーソルを非表示または表示するために使用されます。この関数は、割り込み10H、関数01Hを使用してカーソルタイプを設定します。コーディングは次のとおりです。
show_hide_cursor( ssl, esl )
int ssl, esl ;
{
union REGS i, o ;
i.h.ah = 1 ;
i.h.ch = ssl ;
i.h.cl = esl ;
i.h.bh = 0 ;
int86 ( 16, &i, &o ) ;
return;
}
show_hide_cursor(32、0)はカーソルを非表示にし、show_hide_cursor(6、7)はカーソルを元に戻します。 sslはカーソルの開始行であり、eslはカーソルの終了行です。
INT10Hの機能01Hの簡単な説明は次のとおりです。
INT 10H (16 or 0x10)
関数01H(または0x01) --> カーソルタイプの設定
Call with: AH = 01H
CH bits 0-4 = starting line for cursor
CL bits 0-4 = ending line for cursor
Returns: Nothing.
Comments:
この関数は、テキスト表示モードで点滅しているハードウェアカーソルの開始行と終了行を選択することにより、カーソルタイプを設定するために使用されます。グラフィックモードでは、ハードウェアカーソルは使用できません。