Capítulo – 14
PROGRAMAÇÃO PARA RECUPERAÇÃO DE ARQUIVOS RAW
Recuperando arquivos raw
Existem muitos tipos específicos de arquivos que têm uma sequência ou combinação específica de caracteres escritos no início e no final do arquivo. Podemos analisar facilmente essas combinações usando qualquer programa de edição de disco. Também podemos usar o comando EDIT DOS para examinar a estrutura de um arquivo ASCII.
Uma sequência ou combinação específica de caracteres presentes no início de um arquivo é geralmente chamada de cabeçalho, e uma sequência ou combinação de caracteres armazenada no final de um arquivo é chamada de rodapé do arquivo.
Se perdemos nossos dados em um tipo de falha de disco em que não há informações de FAT ou diretório raiz para recuperar os dados, podemos usar cabeçalhos e rodapés para encontrar esses tipos específicos de arquivos. O cabeçalho indica o início de um arquivo daquele tipo específico, e o rodapé indica o fim de um arquivo daquele tipo específico.
Aqui usamos a estrutura bruta de um determinado tipo de arquivo para recuperar dados, então o método de recuperação é chamado de Recuperação de Arquivo Bruto. A superfície do disco é escaneada setor por setor para encontrar informações de cabeçalho e rodapé.
Embora o Raw File Recovery possa ter uma ampla gama de aplicações, há alguns casos especiais de recuperação em que ele pode ser de grande ajuda. Por exemplo, se você executar por engano qualquer programa de apagamento de dados em um disco que tinha alguns arquivos importantes, todas as informações de MBR, DBR, FAT e diretório raiz, incluindo arquivos do sistema operacional, serão apagadas até que você interrompa o programa.
Nesse caso, mesmo os programas de recuperação de formato podem não ajudar você a recuperar dados. Aqui você pode usar o Raw file Recovery para recuperar arquivos desses tipos específicos pesquisando em cabeçalhos e rodapés.
Além disso, você pode até recuperar dados em casos em que tenha um disco rígido do qual tenha excluído todas as partições lógicas, recriado partições de um tamanho diferente do anterior e até mesmo instalado um sistema operacional.
Agora você obtém a memória que tinha alguns dados importantes no disco antes de ele ser particionado e formatado. Se você acabou de instalar o sistema operacional, há uma boa chance de que o arquivo seja recuperado.
Os fatores que afetam o desempenho da recuperação de arquivos brutos são dados fragmentados e a quantidade de dados substituídos por outros dados. No entanto, você pode encontrar cada vez mais aplicativos para recuperação de arquivos brutos por conta própria.
O procedimento ou quase regras para pesquisar arquivos usando software de recuperação de arquivos brutos leva em consideração as seguintes condições:
- Pesquise um cabeçalho de arquivo ou vários tipos de arquivo simultaneamente em setores do disco.
- Se algum tipo de cabeçalho de arquivo for encontrado, salve os dados no arquivo e verifique as quatro condições a seguir para fechar e salvar o arquivo.
- Foi encontrado rodapé deste tipo de arquivo
- Outro cabeçalho do mesmo tipo de arquivo foi encontrado.
- Cabeçalho encontrado de um tipo de arquivo diferente
- Nenhum outro cabeçalho ou rodapé foi encontrado para determinados tipos de arquivo no programa, e o tamanho do arquivo no qual você está salvando os dados atinge o limite de tamanho máximo definido para o tamanho do arquivo no seu programa.
As informações devem ser salvas no arquivo, incluindo os dados do setor onde você encontrou o cabeçalho e o 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 estão listados na tabela abaixo. Os rodapés listados na tabela estão no final do arquivo do tipo de arquivo especificado ou nos deslocamentos finais do arquivo, para que você possa usá-los como rodapés para recuperação de dados.
Você também pode procurar por cabeçalhos e rodapés diferentes desses tipos de arquivo usando o comando DOS EDIT ou qualquer ferramenta de edição de disco. Usei o sistema hexadecimal para representar as informações e torná-las mais compreensíveis.
Extensão |
Cabeçalho (Hexadecimal) |
Rodapé (Hex) |
DOCUMENTO |
D0 CF 11 E0 A1 B1 1A E1 |
57 6F 72 64 2E 44 6F 63 75 6G 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 |
Código postal |
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 ("É melhor usar a verificação do tamanho do arquivo") |
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 recuperar arquivos raw
Abaixo está a codificação do programa para recuperação de arquivos Raw do Microsoft Word (extensão .DOC). O programa procura arquivos em setores do disco e salva automaticamente o arquivo recuperado, criando automaticamente um nome de arquivo.
O caminho especificado pelo usuário para salvar os arquivos é usado como o caminho de destino para salvar os dados recuperados. Se o diretório de destino não existir, o programa poderá criá-lo em até um nível de diretório.
O software de recuperação fornecido aqui suporta até discos de grande tamanho para pesquisar e recuperar dados. O programa foi escrito para procurar dados em um segundo disco rígido físico.
/* Software de recuperação de arquivos RAW do Microsoft Word */
#incluir<stdio.h>
#include<dos.h>
/* Estrutura usada pela função getdrivegeometry usando a extensão INT 13H, número de função 0x48. */
geometria estrutural
{
tamanho int sem sinal; /* (chamada) tamanho do buffer */
sinalizadores int não assinados; /* Sinalizadores de informação */
cilindro longo sem sinal; /* Número de físicos
Cilindros na unidade */
cabeçalhos longos não assinados ;/* Número de físicos
Cabeças na unidade */
ponto longo não assinado; /* Número de físicos
Setores por trilha */
setor longo não assinado[2] ; /* Quantidade total
Setores no disco */
int sem sinal bps; /* Byte por setor */
} ;
/* Estrutura de formato de pacote de endereço de disco usada por readabsolutesectors */
estrutura diskaddrpacket
{
char tamanho do pacote; /* Tamanho do pacote, geralmente 10H */
símbolo reservado; /* Reservado (0) */
int contagem de blocos; /* Número de blocos a transferir */
char far *endereço do buffer; /* endereço para transmissão
Tampão */
bloco longo sem sinal[2] ; /* Absoluto inicial
Número do bloco */
} ;
///// Função para obter parâmetros de unidade \\\\\
unsigned long getdrivegeometry(intdrive)
{
sindicato REGS i, o ;
estrutura SREGS s;
geometria estrutural g = { 26, 0, 0, 0, 0, 0, 0, 0 } ;
ihah = 0x48 ; /* Número da função 0x48 */
ihdl = unidade; /* Número do disco */
ixsi = FP_OFF ( (void far*)&g ) ;
s.ds = FP_SEG ( (void far*)&g ) ;
/* Chamar o número de função de extensão INT 13H especificado com valores de registro de segmento */
int86x ( 0x13, &i, &o, &s ) ;
printf("\n Cabeça = %lu, Setores por trilha = %lu, Cilindro = %lu\n",
g.cabeça, g.spc, g.cil);
/* Se a função para obter a geometria do disco falhar, imprima uma mensagem de erro e saia */
se(g.spt==0)
{
printf("\n A função para obter a geometria da unidade não foi executada....");
printf("\n Extensões não suportadas, pressione qualquer tecla para
Saída...");
obter();
saída(1);
}
retornar *g.sectors; /* Retorna o número de
Setores em Drive */
}
tamanho_do_arquivo_longo_não_assinado=0, i=0;
arquivo_inicial_longo_não_assinado=0, arquivo_final=0;
unsigned long Setores_em_HDD2=0, loop=0;
char buffer[512], nome do arquivo[80], temp[8];
caminho char[80];
unsigned int resultado,num=0;
/* Cabeçalho de arquivos do Microsoft Word */
char cabeçalho[10] = {0xD0,0xCF,0x11,0xE0, 0xA1,0xB1,0x1A,0xE1};
/* Rodapé de arquivos do Microsoft Word */
char DOC_footer[14] =
{0x57,0x6F,0x72,0x64, 0x2E,0x44,0x6F,0x63,
0x75,0x6D,0x65,0x6E,0x74};
/// Início do main \\\
vazio principal()
{
clrscr();
/* Se o número total de discos rígidos conectados for menor
então dois, Exibir mensagem de erro e Sair. */
se(((char)peekb(0x0040, 0x0075))<2)
{
printf("\n\n Você deve ter pelo menos dois discos rígidos
Anexado ao seu computador para executar isto");
printf("\n Programa. Este programa foi desenvolvido
para recuperar os dados do segundo disco rígido.");
printf("\n Pressione qualquer tecla para sair... ");
obter();
saída(1);
}
Setores_em_HDD2=obtergeometria_do_drive (0x81);
printf("\n Total de setores no segundo disco rígido = %lu",
Setores_em_HDD2);
printf("\n\n \"Você deve salvar os arquivos recuperados em
outro Disco Rígido, Não no Mesmo Disco,");
printf("\n em que você está procurando o perdido
dados.\"");
printf("\n\n Digite o caminho de destino para salvar o
Arquivos recuperados...\n ");
obtém(caminho);
/* verifique se o diretório de destino existe ou não */
se(acesso(caminho, 0) != 0)
{
/* se o diretório de destino não existir, crie
o Diretório até um nível */
se(mkdir(caminho)!=0)
{
printf("\n Não foi possível criar o diretório \"%s\"",
caminho);
printf("\n Verifique o caminho..., Pressione qualquer tecla para
saída...");
obter();
saída(1);
}
}
strcat(caminho,"\\Ptt");
/* Função para ocultar (e mostrar) o cursor na tela */
mostrar_ocultar_cursor ( 32,
gotoxy(15,18);cprintf("[ %d ] Arquivos recuperados...",
num);
/* procura os dados até o setor final do disco */
while(loop<Setores_no_HDD2)
{
/* Ler um setor (Setor No. = loop) */
leiasetoresabsolutos ( 0x81, loop, 1, buffer );
gotoxy(19,16);cprintf("Número do setor de digitalização = % ld",
laço);
se(kbhit())
{
show_hide_cursor ( 6, 7 ); /* Recuperar o
cursor antes
Sair do programa
*/
saída(0);
}
/* se o cabeçalho especificado for encontrado */
if((memcmp(buffer,cabeçalho,7))==0)
{
/* lógica para fornecer o nome do arquivo automaticamente
crie os arquivos para salvar os dados recuperados */
strcpy(nome do arquivo, caminho);
itoa(num,temp,10);
strcat(nome do arquivo, temp);
strcat(nome do arquivo,".DOC");
start_file=loop; /* setor inicial do arquivo */
gotoxy(5,19);cprintf("Arquivo encontrado..., salvando como %s",
nome do arquivo);
num++;
////////////// Condições de fechamento de arquivo \\\\\\\\\\\\\\\\
tamanho_do_arquivo=0;
enquanto( tamanho_do_arquivo < 5000000)
{
laço++;
tamanho_do_arquivo+=512;
leiasetoresabsolutos ( 0x81, loop, 1, buffer );
gotoxy(19,16);cprintf("Número do setor de digitalização = % ld" ,
laço);
/* se o tamanho do arquivo atingir o tamanho máximo de 5 MB */
se(tamanho_do_arquivo>=5000000)
{
end_file=loop; /* Setor final do arquivo */
Recover_the_file();/* escreve os dados no arquivo */
quebrar;
}
/* se o rodapé do arquivo DOC for encontrado */
para(i=0;i<512;i++)
{
se( memcmp(buffer+i,DOC_footer,12)==0 )
{
end_file=loop; /* Setor final do arquivo */
Recover_the_file();/* escreve os dados no arquivo */
quebrar;
}
}
/* se outro cabeçalho for encontrado */
se( memcmp(buffer,cabeçalho,7)==0 )
{
laço=laço-1;
end_file=loop; /* Setor final do arquivo */
Recover_the_file();/* escreve os dados no arquivo */
quebrar;
}
se(kbhit())
{
mostrar_ocultar_cursor ( 6, 7 );
saída(0);
}
}
}
laço++;
}
////////Enquanto o Loop Termina Aqui
/* exibe mensagem para conclusão da pesquisa e recuperação */ if(loop>=Sectors_in_HDD2 )
{
gotoxy(17,23);cprintf("O salvamento de arquivos no disco é
Concluído !!");
gotoxy(17,24);cprintf("Pressione qualquer tecla para sair...");
mostrar_ocultar_cursor ( 6, 7 );
obter();
}
}
A geometria da estrutura é usada pela função getdrivegeometry usando a extensão INT 13H, número de função 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) é obter os parâmetros de unidade do número de unidade física especificado no 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, exiba uma mensagem de erro e saia.
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 declaraçã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 fornecido verificado pela condição if(mkdir(path)!=0) for ilegal, uma mensagem de erro será exibida.
Os nomes de arquivo dos arquivos criados automaticamente para salvar os dados recuperados são criados de forma que os três primeiros caracteres dos arquivos recebam PTT pela função strcat(path,"\\Ptt"); Isso é feito para evitar nomes de arquivo duplicados no diretório de destino. Portanto, os nomes de arquivo dos arquivos recuperados são fornecidos no formato “PTTxxxxx.DOC”
A função show_hide_cursor (32, 0); é usada para ocultar o cursor da tela, enquanto show_hide_cursor (6, 7); recupera o cursor de volta para a tela.
A função readabsolutesectors (0x81, loop, 1, buffer); Lê um setor do segundo disco rígido físico especificado pelo número do setor loop.
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 fornecidas 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 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 começando do número do setor start_file até o número do setor end_file */
Recuperar_o_arquivo()
{
ARQUIVO *fp;
if((fp=fopen(nome do arquivo, "wb"))==NULL)
{
gotoxy(10,23);printf("Erro ao abrir arquivo %s",
nome do arquivo);
obter();
saída(1);
}
para(i=arquivo_inicial;i<=arquivo_final;i++)
{
gotoxy(19,16);cprintf("Número do setor de digitalização =
%ld", i);
leiasetoresabsolutos ( 0x81, i, 1, buffer );
fwrite(buffer,512,1, fp);
}
fclose(fp);
gotoxy(15,18);cprintf("[ %d ] Arquivos recuperados...",num);
gotoxi(5,19);cprintf(" ");
retornar;
}
A codificação da função readabsolutesectors foi dada a seguir. A função usa a extensão INT 13H e o número de função 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 unidade,
número de setor longo sem sinal,
int número de setores,
vazio *buffer )
{
união REGS i, o ;
estrutura SREGS s ;
estrutura diskaddrpacket pp;
pp.packetsize = 16 ; /* tamanho do pacote = 10H */
pp.reserved = 0 ; /* Reservado = 0 */
pp.blockcount = numofsectors ; /* Número de setores
ler */
/* para buffer de dados */
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void far*)buffer), FP_OFF((void far*)buffer));
pp.blocknumber[0] = sectornumber ; /* Número do setor
ler */
pp.blocknumber[1] = 0 ; /* Número do bloco */
ihah = 0x42 ; /* Número da função*/
ihdl = drive ; /* Número da unidade física */
/* ds:si para parâmetros de buffer */
ixsi = FP_OFF ( (void far*)&pp ) ;
/* ds:si para parâmetros de buffer */
s.ds = FP_SEG ( (void far*)&pp ) ;
/* Invoca a função especificada de INT 13H com
valores de registro de segmento */
int86x ( 0x13, &i, &o, &s ) ;
se (oxcflag==1)
retornar 0 ; //falha
outro
retornar 1 ; // sucesso
}
A função a seguir é usada para ocultar ou mostrar o cursor na tela. A função usa a interrupção 10H, função 01H para definir o tipo de cursor. A codificação é a seguinte:
mostrar_ocultar_cursor(ssl, esl)
inteiros ssl, esl;
{
sindicato REGS i, o ;
aumento = 1 ;
ihch = ssl ;
ihcl = esl ;
ihbh = 0 ;
int86 ( 16, &i, &o ) ;
voltar;
}
show_hide_cursor( 32, 0 ) oculta o cursor e show_hide_cursor( 6, 7 ) traz o cursor de volta. ssl é a linha inicial do cursor e esl é a linha final do cursor.
Uma breve descrição da função 01H INT 10H é a seguinte:
INT 10H (16 ou 0x10)
Função 01H (ou 0x01) --> Definir tipo de cursor
Chamada de: AH = 01H
Bits 0-4 CH = Linha inicial para cursor
Bits CL 0-4 = fim de linha para cursor
Retorno: nada.
Comentários:
A função é usada para definir o tipo de cursor selecionando as linhas inicial e final do cursor de hardware piscante no modo de exibição de texto. O cursor de hardware não está disponível em modos gráficos.