Представьте, что вы удалили фотографии с карты памяти, а потом захотели их восстановить. Оказывается, что в некоторых случаях это возможно сделать, ведь когда мы удаляем фото кнопкой «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; }