Chapitre – 14
PROGRAMMATION POUR LA RÉCUPÉRATION DE FICHIERS RAW
Récupération de fichiers bruts
Il existe de nombreux types de fichiers spécifiques qui ont une séquence ou une combinaison spécifique de caractères écrits au début et à la fin du fichier. Nous pouvons facilement analyser ces combinaisons à l’aide de n’importe quel programme d’édition de disque. Nous pouvons également utiliser la commande DOS EDIT pour examiner la structure d'un fichier ASCII.
Une séquence ou une combinaison particulière de caractères présente au début d'un fichier est généralement appelée en-tête, et une séquence ou une combinaison de caractères stockée à la fin d'un fichier est appelée pied de page du fichier.
Si nous avons perdu nos données dans un tel type de panne de disque qu'il n'y a pas d'informations sur le FAT ou le répertoire racine pour récupérer les données, nous pouvons utiliser des en-têtes et des pieds de page pour trouver ces types de fichiers spécifiques. L'en-tête indique le début d'un fichier de ce type de fichier particulier, et le pied de page indique la fin d'un fichier de ce type de fichier particulier.
Ici, nous utilisons la structure brute d'un certain type de fichier pour récupérer des données, la méthode de récupération est donc appelée récupération de fichier brut. La surface du disque est analysée secteur par secteur pour trouver des informations d'en-tête et de pied de page.
Bien que Raw File Recovery puisse avoir une large gamme d'applications, il existe des cas de récupération particuliers où il peut être d'une grande aide. Par exemple, si vous exécutez par erreur un programme d'effacement de données sur un disque contenant des fichiers importants, mais que vous n'arrêtez pas le programme, toutes les informations MBR, DBR, FAT et du répertoire racine, y compris les fichiers du système d'exploitation, seront effacées.
Dans ce cas, même les programmes de récupération de format peuvent ne pas vous aider à récupérer les données. Ici, vous pouvez utiliser Raw File Recovery pour récupérer des fichiers de ces types de fichiers spécifiques en recherchant dans les en-têtes et les pieds de page.
De plus, vous pouvez même récupérer des données dans les cas où vous avez un disque dur sur lequel vous avez supprimé toutes les partitions logiques du lecteur, recréé des partitions d'une taille différente de celle d'avant et même installé un système d'exploitation.
Vous récupérez maintenant la mémoire indiquant que vous aviez des données importantes sur le disque avant qu'il ne soit partitionné et formaté. Si vous venez d'installer le système d'exploitation, il y a de fortes chances que le fichier soit récupéré.
Les facteurs qui affectent les performances de récupération des fichiers bruts sont les données fragmentées et la quantité de données écrasées par d’autres données. Cependant, vous pouvez trouver de plus en plus d'applications pour la récupération de fichiers bruts par vous-même.
La procédure ou presque les règles de recherche de fichiers à l'aide d'un logiciel de récupération de fichiers bruts prennent en compte les conditions suivantes :
- Rechercher un en-tête de fichier ou plusieurs types de fichiers simultanément dans les secteurs du disque.
- Si un en-tête de type de fichier est trouvé, enregistrez les données dans le fichier et vérifiez les quatre conditions suivantes pour fermer et enregistrer le fichier.
- Pied de page trouvé pour ce type de fichier
- Un autre en-tête du même type de fichier a été trouvé.
- En-tête trouvé d'un type de fichier différent
- Aucun autre en-tête ou pied de page n'a été trouvé pour certains types de fichiers dans le programme, et la taille du fichier dans lequel vous enregistrez les données atteint la limite de taille maximale que vous avez définie pour la taille du fichier dans votre programme.
Les informations doivent être enregistrées dans le fichier, y compris les données du secteur où vous avez trouvé l'en-tête et le pied de page du type de fichier.
En-têtes et pieds de page de certains types de fichiers importants
Les en-têtes et pieds de page de certains types de fichiers importants sont répertoriés dans le tableau ci-dessous. Les pieds de page répertoriés dans le tableau se trouvent soit à la fin du fichier du type de fichier spécifié, soit aux décalages de fin du fichier, vous pouvez donc les utiliser comme pieds de page pour la récupération de données.
Vous pouvez également rechercher vous-même des en-têtes et des pieds de page autres que ces types de fichiers à l'aide de la commande DOS EDIT ou de n'importe quel outil d'édition de disque. J'ai utilisé le système hexadécimal pour représenter les informations afin de les rendre plus compréhensibles.
Extension |
En-tête (hexadécimal) |
Pied de page (Hex) |
DOC |
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 |
Présentation PowerPoint |
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 |
Code 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 (« Il est préférable d'utiliser la vérification de la taille du fichier ») |
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 |
Écrire un programme pour récupérer des fichiers bruts
Vous trouverez ci-dessous le codage du programme de récupération de fichiers bruts des fichiers Microsoft Word (extension .DOC). Le programme recherche les fichiers dans les secteurs du disque et enregistre automatiquement le fichier récupéré, créant automatiquement un nom de fichier.
Le chemin spécifié par l'utilisateur pour enregistrer les fichiers est utilisé comme chemin de destination pour enregistrer les données récupérées. Si le répertoire de destination n'existe pas, le programme peut le créer jusqu'à un niveau de répertoire.
Le logiciel de récupération fourni ici prend en charge même les disques de grande taille pour rechercher et récupérer des données. Le programme a été écrit pour rechercher des données sur un deuxième disque dur physique.
/* Logiciel de récupération de fichiers RAW Microsoft Word */
#include<stdio.h>
#include<dos.h>
/* Structure utilisée par la fonction getdrivegeometry utilisant l'extension INT 13H, numéro de fonction 0x48. */
géométrie structurelle
{
int non signé taille ; /* (appel) taille du tampon */
drapeaux int non signés ; /* Drapeaux d'information */
cylindre long non signé ; /* Nombre de physiques
Cylindres sur le lecteur */
en-têtes longs non signés ;/* Nombre de
Têtes sur le disque */
spt long non signé ; /* Nombre de physiques
Secteurs par piste */
secteur long non signé[2] ; /* Quantité totale
Secteurs sur le disque */
int non signé bps ; /* Octet par secteur */
} ;
/* Structure de format de paquet d'adresse de disque utilisée par readabsolutesectors */
Structure du paquet diskaddr
{
taille du paquet char ; /* Taille du paquet, généralement 10H */
symbole réservé ; /* Réservé (0) */
int nombre de blocs ; /* Nombre de blocs à transférer */
char loin *bufferaddress ; /* adresse de transmission
Tampon */
numéro de bloc non signé long[2] ; /* Initial absolu
Numéro de bloc */
} ;
///// Fonction permettant d'obtenir les paramètres du lecteur \\\\\
unsigned long getdrivegeometry(intdrive)
{
syndicat REGS i, o ;
structures SREGS;
géométrie structurelle g = { 26, 0, 0, 0, 0, 0, 0, 0 } ;
iha = 0x48 ; /* Numéro de fonction 0x48 */
ihdl = lecteur; /* Numéro de disque */
ixsi = FP_OFF ( (void far*)&g ) ;
s.ds = FP_SEG ( (void far*)&g ) ;
/* Appelez le numéro de fonction d'extension INT 13H spécifié avec les valeurs de registre de segment */
int86x ( 0x13, &i, &o, &s ) ;
printf("\n Tête = %lu, Secteurs par piste = %lu, Cylindre = %lu\n",
g.tête, g.spc, g.cyl);
/* Si la fonction permettant d'obtenir la géométrie du disque échoue, imprimez un message d'erreur et quittez */
si(g.spt==0)
{
printf("\n La fonction permettant d'obtenir la géométrie du lecteur n'a pas été exécutée....");
printf("\n Extensions non prises en charge, appuyez sur n'importe quelle touche pour
Sortie...");
obtenir();
sortie(1);
}
retourner *g.sectors; /* Renvoyer le nombre de
Secteurs sur Drive */
}
taille_du_fichier non signé=0, i=0;
unsigned long début_fichier=0, fin_fichier=0;
unsigned long Secteurs_dans_HDD2=0, boucle=0 ;
char buffer[512], nom de fichier[80], temp[8];
chemin de caractère[80];
int non signé résultat,num=0;
/* En-tête des fichiers Microsoft Word */
en-tête de caractère [10] = {0xD0,0xCF,0x11,0xE0, 0xA1,0xB1,0x1A,0xE1};
/* Pied de page des fichiers Microsoft Word */
char DOC_footer[14] =
{0x57,0x6F,0x72,0x64, 0x2E,0x44,0x6F,0x63,
0x75,0x6D,0x65,0x6E,0x74};
/// Début du principal \\\
void main()
{
clrscr();
/* Si le nombre total de disques durs connectés est inférieur
puis deux, afficher un message d'erreur et quitter. */
si(((char)peekb(0x0040, 0x0075))<2)
{
printf("\n\n Vous devez avoir au moins deux disques durs
Connecté à votre ordinateur pour exécuter ceci » );
printf("\n Programme. Ce programme a été développé
pour récupérer les données du deuxième disque dur.");
printf("\n Appuyez sur n'importe quelle touche pour quitter... ");
obtenir();
sortie(1);
}
Secteurs_dans_HDD2=getdrivegeometry (0x81);
printf("\n Nombre total de secteurs sur le deuxième disque dur = %lu",
Secteurs_dans_HDD2);
printf("\n\n \"Vous devez enregistrer les fichiers récupérés dans
un autre disque dur, pas sur le même disque,");
printf("\n dans lequel vous recherchez le perdu
données.\"");
printf("\n\n Entrez le chemin de destination pour enregistrer le
Fichiers récupérés...\n ");
obtient(chemin);
/* vérifier si le répertoire de destination existe ou non */
si(accès(chemin, 0) != 0)
{
/* si le répertoire de destination n'existe pas, créez
le Répertoire jusqu'à un niveau */
si(mkdir(chemin)!=0)
{
printf("\n Impossible de créer le répertoire \"%s\"",
chemin);
printf("\n Vérifier le chemin..., Appuyez sur n'importe quelle touche pour
sortie...");
obtenir();
sortie(1);
}
}
strcat(chemin,"\\Ptt");
/* Fonction pour masquer (et afficher) le curseur sur l'écran */
afficher_masquer_curseur ( 32,
gotoxy(15,18);cprintf("[ %d ] Fichiers récupérés...",
dans);
/* rechercher les données jusqu'au dernier secteur du disque */
while(boucle<Secteurs_dans_HDD2)
{
/* Lire un secteur (Numéro de secteur = boucle) */
readabsolutesectors ( 0x81, boucle, 1, tampon );
gotoxy(19,16);cprintf("Numéro de secteur d'analyse = % ld",
boucle);
si(kbhit())
{
show_hide_cursor ( 6, 7 ); /* Récupérer le
curseur avant
Quitter le programme
*/
sortie(0);
}
/* si l'en-tête spécifié est trouvé */
si((memcmp (tampon, en-tête,7))==0)
{
/* logique pour fournir automatiquement le nom du fichier
créer les fichiers pour sauvegarder les données récupérées */
strcpy(nom de fichier, chemin);
itoa(num,temp,10);
strcat(nom de fichier, temp);
strcat(nom de fichier,".DOC");
start_file=loop; /* secteur de départ du fichier */
gotoxy(5,19);cprintf("Fichier trouvé..., Enregistrement sous %s",
nom de fichier);
nombre++;
////////////// Conditions de fermeture du fichier \\\\\\\\\\\\\\\
taille_du_fichier=0;
tandis que( taille_fichier<5000000)
{
boucle++;
taille_fichier+=512;
readabsolutesectors ( 0x81, boucle, 1, tampon );
gotoxy(19,16);cprintf("Numéro de secteur d'analyse = % ld" ,
boucle);
/* si la taille du fichier atteint la taille maximale de 5 Mo */
si (taille_fichier>=5000000)
{
end_file=loop; /* Secteur de fin du fichier */
Recover_the_file();/* écrire les données dans le fichier */
casser;
}
/* si le pied de page du fichier DOC est trouvé */
pour(i=0;i<512;i++)
{
si( memcmp(buffer+i,DOC_footer,12)==0 )
{
end_file=loop; /* Secteur de fin du fichier */
Recover_the_file();/* écrire les données dans le fichier */
casser;
}
}
/* si un autre en-tête est trouvé */
si( memcmp(tampon,en-tête,7)==0 )
{
boucle=boucle-1;
end_file=loop; /* Secteur de fin du fichier */
Recover_the_file();/* écrire les données dans le fichier */
casser;
}
si(kbhit())
{
afficher_masquer_curseur ( 6, 7 );
sortie(0);
}
}
}
boucle++;
}
////////La boucle While se termine ici
/* afficher un message pour l'achèvement de la recherche et de la récupération */ if(loop>=Sectors_in_HDD2 )
{
gotoxy(17,23);cprintf("L'enregistrement des fichiers sur le disque est
Complété !!");
gotoxy(17,24);cprintf("Appuyez sur n'importe quelle touche pour quitter...");
afficher_masquer_curseur ( 6, 7 );
obtenir();
}
}
La géométrie de la structure est utilisée par la fonction getdrivegeometry utilisant l'extension INT 13H, numéro de fonction 0x48 pour obtenir les différents paramètres du disque.
La structure diskaddrpacket est destinée au format de paquet d'adresse de disque, à utiliser par la fonction readabsolutesectors.
La fonction getdrivegeometry (int drive) permet d'obtenir les paramètres du lecteur du disque physique spécifié numéro de lecteur.
(char) peekb(0x0040, 0x0075) est utilisé pour trouver le nombre de disques durs connectés à l'ordinateur, stockés à l'emplacement mémoire représenté par le segment 0040H:offset 0075H. Si le nombre total de disques durs connectés est inférieur à deux, affichez un message d'erreur et quittez.
Sectors_in_HDD2=getdrivegeometry (0x81) ; recherche les différents paramètres du deuxième disque dur physique (0x81) et renvoie le nombre total de secteurs du disque.
L'instruction if(access(path, 0) != 0) vérifie l'accessibilité du chemin donné par l'utilisateur. Si le répertoire de destination n'existe pas, la destination est créée jusqu'à un niveau et si le chemin donné vérifié par la condition if(mkdir(path)!=0) est illégal, un message d'erreur est affiché.
Les noms de fichiers créés automatiquement pour sauvegarder les données récupérées sont créés de telle sorte que les trois premiers caractères des fichiers reçoivent PTT par la fonction strcat(path,"\\Ptt");. Cela permet d'éviter les noms de fichiers en double dans le répertoire de destination. Par conséquent, les noms de fichiers des fichiers récupérés sont donnés au format « PTTxxxxx.DOC »
La fonction show_hide_cursor (32, 0); est utilisée pour masquer le curseur de l'écran où show_hide_cursor (6, 7); récupère le curseur à l'écran.
La fonction readabsolutesectors (0x81, boucle, 1, tampon) ; lit un secteur du deuxième disque dur physique spécifié par le numéro de secteur en boucle.
Si l'en-tête du fichier est trouvé, start_file = loop; définit start_file sur le numéro de secteur de départ du fichier à récupérer. Le programme suit les trois conditions données ci-après pour trouver le secteur de fin du fichier :
- Si la taille du fichier atteint la taille maximale de 5 Mo
- Si le pied de page du fichier DOC est trouvé
- Si un autre en-tête est trouvé
L'entier long end_file est défini sur le numéro de secteur de fin du fichier par end_file=loop; si l'une des trois conditions est satisfaite. Maintenant, les données des secteurs, à partir du numéro de secteur start_file jusqu'au numéro de secteur end_file, sont enregistrées dans le fichier avec la fonction Recover_the_file( ).
Le codage de la fonction Recover_the_file( ) a été donné ci-dessous :
/* Fonction permettant de sauvegarder les données des secteurs à partir du numéro de secteur start_file jusqu'au numéro de secteur end_file */
Récupérer_le_fichier()
{
FICHIER *fp;
si((fp=fopen(nom de fichier, "wb"))==NULL)
{
gotoxy(10,23);printf("Erreur lors de l'ouverture du fichier %s",
nom de fichier);
obtenir();
sortie(1);
}
pour(i=fichier_début;i<=fichier_fin;i++)
{
gotoxy(19,16);cprintf("Numéro de secteur d'analyse =
%ld", i);
lire les secteurs absolus ( 0x81, i, 1, tampon );
fwrite(tampon,512,1, fp);
}
fclose(fp);
gotoxy(15,18);cprintf("[ %d ] Fichiers récupérés...",num);
gotoxy(5,19);cprintf(" ");
retour;
}
Le codage de la fonction readabsolutesectors est donné ci-après. La fonction utilise l'extension INT 13H et le numéro de fonction 42H pour lire les secteurs.
Pour une description détaillée de la fonction, reportez-vous au chapitre « Réalisation de sauvegardes » abordé plus haut dans ce livre. Le codage de la fonction est le suivant :
//// Fonction de lecture de secteur(s) absolu(s) \\\\
int readabsolutesectors ( int lecteur,
numéro de secteur non signé long,
int nombre de secteurs,
vide *tampon )
{
syndicat REGS i, o ;
structure SREGS s ;
struct diskaddrpacket pp ;
pp.packetsize = 16 ; /* taille du paquet = 10H */
pp.reserved = 0 ; /* Réservé = 0 */
pp.blockcount = numofsectors ; /* Nombre de secteurs
à lire */
/* pour le tampon de données */
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void far*)tampon), FP_OFF((void far*)tampon));
pp.blocknumber[0] = sectornumber ; /* Numéro de secteur
à lire */
pp.blocknumber[1] = 0 ; /* Numéro de bloc */
ihah = 0x42 ; /* Numéro de fonction*/
ihdl = lecteur ; /* Numéro de lecteur physique */
/* ds:si pour les paramètres du tampon */
ixsi = FP_OFF ( (void far*)&pp ) ;
/* ds:si pour les paramètres du tampon */
s.ds = FP_SEG ( (void far*)&pp ) ;
/* Invoquer la fonction spécifiée de INT 13H avec
valeurs du registre de segment */
int86x ( 0x13, &i, &o, &s ) ;
si ( oxcflag==1)
retour 0 ; //échec
autre
retour 1 ; // succès
}
La fonction suivante est utilisée pour masquer ou afficher le curseur sur l'écran. La fonction utilise l'interruption 10H, fonction 01H pour définir le type de curseur. Le codage est le suivant :
afficher_masquer_curseur( ssl, esl )
entiers ssl, esl ;
{
syndicat REGS i, o ;
augmentation = 1 ;
jehch = ssl ;
ihcl = esl ;
jhbh = 0 ;
int86 ( 16, &i, &o ) ;
revenir;
}
show_hide_cursor( 32, 0 ) masque le curseur, et show_hide_cursor( 6, 7 ) ramène le curseur. ssl est la ligne de départ du curseur et esl est la ligne de fin du curseur.
Une brève description de la fonction 01H INT 10H est la suivante :
INT 10H (16 ou 0x10)
Fonction 01H (ou 0x01) --> Définir le type de curseur
Appel depuis : AH = 01H
Bits 0-4 CH = Ligne de départ pour le curseur
CL bits 0-4 = fin de ligne pour le curseur
Retour : rien.
Commentaires:
La fonction permet de définir le type de curseur en sélectionnant les lignes de début et de fin du curseur matériel clignotant en mode d'affichage de texte. Le curseur matériel n'est pas disponible dans les modes graphiques.