Imagine that you deleted photos from your memory card and then wanted to restore them. It turns out that in some cases it is possible to do this, because when we delete a photo with the “delete” button, what actually happens is more like not deleting, but forgetting. The links between the bytes are lost, but the information itself is still in memory until it is overwritten with new photographs. Passing the CS50 course (Harvard) – at the end of the fourth week, we got the recover.c task, in which we are given the source file of the memory card card.raw and need to write a program that will restore all the photos.
Digital cameras often store photographs one after another in accordance with the FAT file system, where all information is divided into blocks of the same size of 512 bytes. And each photo is recorded using these blocks. Considering that photos can differ slightly in size from each other, but at the same time be recorded in the same number of blocks, it allows you to write code that sequentially goes through each block of the card’s memory and copies this data into new files. The “extra” bytes are called “unallocated space”, and even ancient photographs can be stored in it.
Code of programme (Shtukensia)
#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; }
Programme (igroglaz):
#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; }