Capítulo – 14
Programação para recuperação de “arquivos brutos”
Recuperação de arquivos brutos
Existem muitos tipos de arquivos específicos que possuem alguma sequência específica ou combinação de caracteres escritos no início e no final do arquivo. Podemos analisar essas combinações facilmente com a ajuda de qualquer programa de edição de disco. Também podemos usar o comando EDIT do DOS para estudar a estrutura do arquivo no formato ASCII.
A sequência ou combinação de caracteres específica que está presente no início do arquivo é geralmente chamada de cabeçalho e a sequência ou combinação de caracteres armazenada no final do arquivo é chamada de rodapé do arquivo.
Se perdemos nossos dados em tal tipo de falha de disco que nenhuma informação de FAT ou Diretório Raiz está disponível para recuperar os dados, podemos usar cabeçalhos e rodapés para pesquisar esses tipos de arquivo específicos. O cabeçalho indica o início do arquivo desse tipo específico e o rodapé indica o final do arquivo desse tipo de arquivo específico.
Aqui estamos usando a estrutura bruta de um tipo de arquivo específico para recuperar os dados, portanto, a técnica de recuperação é chamada de Recuperação de arquivo bruto. A superfície do disco é pesquisada setor a setor para encontrar as informações de cabeçalho e rodapé.
Embora a Recuperação de Arquivos Brutos possa ter uma ampla área de aplicação, mas existem alguns casos específicos de recuperação onde ela pode ajudar bastante. Por exemplo, por engano, se você executou algum programa de limpeza de dados no disco que tinha alguns arquivos importantes, mas até que você pare o programa, todas as informações do diretório MBR, DBR, FAT e raiz, incluindo arquivos do sistema operacional, serão apagadas.
Nesse caso, mesmo os programas de recuperação de formato podem não ajudá-lo a recuperar os dados. Aqui você pode usar o Raw file Recovery para recuperar os arquivos desses tipos de arquivo específicos pesquisando os cabeçalhos e rodapés.
Não apenas isso, até mesmo você pode recuperar dados em tais casos, onde você tem um disco rígido no qual excluiu todas as partições lógicas do disco, recriou as partições de tamanho diferente de antes e até mesmo instalou o sistema operacional.
Agora você se lembra de que tinha alguns dados importantes no disco antes de particioná-lo e formatá-lo. Se você acabou de instalar o sistema operacional, há muitas chances de o arquivo ser recuperado.
Os fatores que afetam o desempenho do Raw File Recovery são, dados fragmentados e a quantidade de dados sobrescritos por alguns outros dados. No entanto, você pode encontrar mais e mais áreas de aplicação para recuperação de arquivos brutos.
O procedimento ou quase as regras para pesquisar os arquivos com o programa de recuperação de arquivos brutos consideram as seguintes condições:
- Pesquise o cabeçalho do arquivo ou vários tipos de arquivos simultaneamente nos setores do disco.
- Se o cabeçalho de qualquer tipo de arquivo for encontrado, salve os dados em um arquivo e verifique as quatro condições a seguir para fechar e salvar o arquivo
- O rodapé desse tipo de arquivo foi encontrado
- O outro cabeçalho do mesmo tipo de arquivo foi encontrado
- O cabeçalho de outro tipo de arquivo foi encontrado
- Nenhum outro cabeçalho ou rodapé para os tipos de arquivo definidos no programa é encontrado e o tamanho do arquivo no qual você está armazenando os dados atinge o limite máximo de tamanho definido para o tamanho do arquivo em seu programa.
As informações devem ser armazenadas no arquivo incluindo os dados dos setores em que você encontrou o cabeçalho e rodapé do tipo de arquivo.
Cabeçalhos e rodapés de alguns tipos de arquivos importantes
Os cabeçalhos e rodapés de alguns tipos de arquivos importantes foram fornecidos na tabela a seguir. Os rodapés fornecidos na tabela estão no final do arquivo do tipo de arquivo especificado ou estão nos deslocamentos finais do arquivo, de modo que você possa usá-los como rodapés para recuperar os dados.
Você também pode pesquisar cabeçalhos e rodapés, diferentes desses tipos de arquivo, usando o comando EDIT do DOS ou usando qualquer ferramenta de edição de disco. Eu usei o sistema hexadecimal para representar as informações para facilitar o entendimento.
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 |
Escrevendo um programa para recuperação de arquivos brutos
A codificação do programa para recuperação de arquivos brutos de arquivos do Microsoft Word (extensão .DOC) foi apresentada a seguir. O programa procura os arquivos nos setores do disco e salva o arquivo recuperado automaticamente criando o nome do arquivo automaticamente.
O caminho especificado pelo usuário para salvar os arquivos é usado como caminho de destino para salvar os dados recuperados. Se o diretório de destino não existir, o programa pode criar o destino em até um nível de diretório.
O programa de recuperação fornecido aqui suporta até mesmo os discos de tamanho grande para pesquisar e recuperar os dados. O programa foi escrito para pesquisar os dados no segundo disco rígido físico.
/* Programa de recuperação de arquivos brutos para recuperar os arquivos do Microsoft Word */
#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 */
} ;
///// Função para obter os parâmetros do inversor \\\\\
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;
/* Cabeçalho de arquivos do Microsoft Word */
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");
/* Função para ocultar (e mostrar) o cursor na tela */
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++;
////////////// Condições de fechamento de arquivo \\\\\\\\\\\\\\\\
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++;
}
////////Enquanto o loop termina aqui
/* 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();
}
}
A geometria da estrutura é usada pela função getdrivegeometry usando INT 13H Extension, Function Number 0x48 para obter os vários parâmetros do disco.
A estrutura diskaddrpacket é para o formato de pacote de endereço de disco, a ser usado pela função readabsolutesectors.
A função getdrivegeometry (int drive) é para obter os parâmetros de unidade da unidade de número de unidade física especificada do disco.
(char) peekb(0x0040, 0x0075) é usado para encontrar o número de discos rígidos conectados ao computador, armazenados no local de memória representado pelo segmento 0040H:offset 0075H. Se o número total de discos rígidos conectados for menor que dois Exibir mensagem de erro e sair.
Sectors_in_HDD2=getdrivegeometry (0x81); encontra os vários parâmetros do segundo disco rígido físico (0x81) e retorna o número total de setores do disco.
A instrução if(access(path, 0) != 0) verifica a acessibilidade do caminho fornecido pelo usuário. Se o diretório de destino não existir, o destino será criado até um nível e se o caminho determinado verificado pela condição if(mkdir(path)!=0) for ilegal, uma mensagem de erro será exibida.
Os nomes dos arquivos criados automaticamente para salvar os dados recuperados são criados de forma que os três primeiros caracteres dos arquivos recebam PTT por strcat(path,"\\Ptt"); função. Isso é feito para evitar nomes de arquivos duplicados no diretório de destino. Portanto, os nomes dos arquivos recuperados são fornecidos no formato “PTTxxxxx.DOC”
A função show_hide_cursor ( 32, 0 ); é usado para Ocultar o Cursor da tela onde show_hide_cursor ( 6, 7 ); recupera o cursor de volta à tela.
A função readabsolutesectors (0x81, loop, 1, buffer); Lê um setor do segundo disco rígido físico especificado pelo loop do número do setor.
Se o cabeçalho do arquivo for encontrado, start_file = loop; define o start_file para o número do setor inicial do arquivo a ser recuperado. O programa segue as três condições dadas a seguir, para encontrar o setor final do arquivo:
- Se o tamanho do arquivo atingir o tamanho máximo de 5 MB
- Se o rodapé do arquivo DOC for encontrado
- Se outro cabeçalho for encontrado
O número inteiro longo end_file é definido como o número do setor final do arquivo por end_file=loop; se qualquer uma das três condições for satisfeita. Agora os dados dos setores, começando do número do setor start_file até o número do setor end_file são salvos no arquivo com a função Recover_the_file( ).
A codificação da função Recover_the_file( ) foi dada a seguir:
/* Função para salvar os dados dos setores a partir do número do setor start_file até o número do setor 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;
}
A codificação da função readabsolutesectors foi dada a seguir. A função usa a extensão INT 13H e a função número 42H para ler os setores.
Para a descrição detalhada da função, consulte o capítulo “Fazendo Backups” discutido anteriormente neste livro. A codificação da função é a seguinte:
//// Função para ler setor(es) absoluto(s)\\\\
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
}
A seguinte função é usada para ocultar ou mostrar o cursor na tela. A função usa Interromper 10H, Função 01H para definir o tipo de cursor. A codificação é a seguinte:
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 ) oculta o cursor e show_hide_cursor( 6, 7 ) recupera o cursor de volta. ssl está começando a linha para o cursor e esl está terminando a linha para o cursor.
A pequena descrição da Função 01H de INT 10H é a seguinte:
INT 10H (16 ou 0x10)
Função 01H (ou 0x01) --> Definir tipo de cursor
Call with: AH = 01H
CH bits 0-4 = starting line for cursor
CL bits 0-4 = ending line for cursor
Returns: Nothing.
Comments:
A função é usada para definir o tipo de cursor selecionando as linhas inicial e final para o cursor de hardware piscando no modo de exibição de texto. Nos modos gráficos, o cursor de hardware não está disponível.
Página modificada em: 17/01/2022