Представьте, что вы удалили фотографии с карты памяти, а потом захотели их восстановить. Оказывается, что в некоторых случаях это возможно сделать, ведь когда мы удаляем фото кнопкой «delete», то что происходит на самом деле больше похоже не на удаление, а на забывание. Связи между байтами пропадают, но сама информация все еще находится в памяти, пока не будет перезаписана новыми фотографиями. Проходя курс CS50 (Harvard) — в конце четвертой недели нам выпало задание recover.c, в котором нам дается исходный файл карты памяти card.raw и нужно написать программу, которая восстановит все фотографии.
Цифровые камеры зачастую хранят фотографии друг за другом в соответствии с файловой системой FAT, где вся информация разделяется на блоки одинакового размера по 512 байт. И каждая фотография записывается при помощи этих блоков. Учитывая, что фотографии могут незначительно отличаться по размеру друг от друга, но при этом записываться одинаковым количеством блоков, позволяет написать код, который последовательно пройдет по каждому блоку памяти карты и скопирует эти данные в новые файлы. «Лишние» байты называются «незанятым пространством», и в нем может сохраниться что-то даже из древних фотографий.
Код программы (Штукенция)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// Check command-line arguments (should take 1 command-line argument)
if (argc != 2)
{
printf("Usage: ./recover YOUR_IMAGE.raw\n");
return 1;
}
// Open memory card and check if it can be openned for reading
FILE *image_raw = fopen(argv[1], "r");
if (image_raw == NULL)
{
printf("The forensic image cannot be opened for reading\n");
return 1;
}
typedef uint8_t BYTE; // 1 byte = 8 bit unsigned int
int BLOCK_SIZE = 512; // Size of each block of JPG files
BYTE buffer[BLOCK_SIZE]; // Initialized the buffer for temporary data from file
int amount_jpg = 0; // How many JPG files have been written
int jpg_found = 0; // If JPG found = 1
char filename[8]; // store xxx.JPG names + /0
FILE *img = NULL; // New files for JPGs
// Repeat until reach the end of the file
while (fread(buffer, BLOCK_SIZE, 1, image_raw)) // Read 512 Bytes to a Buffer for data from memory card
{
// if starts the new JPG
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if it was NOT the first JPG
if (amount_jpg > 0)
{
fclose(img); // Close previously written file
}
// if it was first JPG
sprintf(filename, "%03i.jpg", amount_jpg); // Store name for new JPG in buffer
img = fopen(filename, "w"); // open new JPG file from 001.JPG
fwrite(buffer, BLOCK_SIZE, 1, img); // write header block to JPG
amount_jpg += 1;
jpg_found = 1;
}
// if it's not the beginning of JPG
else
{
// if already found JPG
if (jpg_found == 1)
{
fwrite(buffer, BLOCK_SIZE, 1, img); // write from 001.JPG and put data there
}
}
}
// programm reached the end of the file -> close files
fclose(img);
fclose(image_raw);
return 0;
}
Код программы (Игроглаз):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
typedef uint8_t BYTE;
BYTE *buffer = (BYTE *)malloc(512);
FILE *new_file = NULL; // we have to make it there to solve scope problem
int img_num = 0;
char *file_num = (char *)malloc(8); // "###.jpg" is 7+1 bytes (additional 1 is for \0)
if (argc != 2)
{
printf("Usage: ./recover <file>\n");
return 1;
}
FILE *file = fopen(argv[1], "rb");
if (file == NULL)
{
printf("File can't be opened\n");
return 1;
}
// use fread() to write chunk of 512 bytes to a buffer
while (fread(buffer, 1, 512, file) == 512) // fread() return number of bytes it has read
{
// check first 4 bytes for a jpg signature
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && // start of new jpg
((buffer[3] & 0xf0) == 0xe0)) // for buffer[3] first four bits must be 1110
{
if (img_num == 0) // 1st image
{
// put chunk to a new file, from 000.jpg up to 999.jpg
sprintf(file_num, "%03i.jpg", img_num++);
new_file = fopen(file_num, "wb");
fwrite(buffer, 1, 512, new_file);
}
else // we already have file, so close it and open new one
{
fclose(new_file);
sprintf(file_num, "%03i.jpg", img_num++);
new_file = fopen(file_num, "wb");
fwrite(buffer, 1, 512, new_file);
}
}
// if chunk is not start of a new file - continue writing it to existent one
else if (img_num > 0) // new_file must be defined
{
fwrite(buffer, 1, 512, new_file);
}
}
free(buffer);
free(file_num);
fclose(new_file);
fclose(file);
return 0;
}
