I have been struggling with the 'recover' program for a few hours and cannot seem to find the issue.
I thought I had already closed all the files, and I haven't used the 'malloc' syntax for memory allocation.
Could you please provide me with some hints or guidance? Thank you very much!
I've also tried using Valgrind, and it's showing something like this:
==34245== Memcheck, a memory error detector
==34245== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==34245== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==34245== Command: ./recover card.raw
==34245==
==34245==
==34245== HEAP SUMMARY:
==34245== in use at exit: 944 bytes in 2 blocks
==34245== total heap usage: 104 allocs, 102 frees, 233,912 bytes allocated
==34245==
==34245== 944 bytes in 2 blocks are still reachable in loss record 1 of 1
==34245== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==34245== by 0x4A076CD: __fopen_internal (iofopen.c:65)
==34245== by 0x4A076CD: fopen@@GLIBC_2.2.5 (iofopen.c:86)
==34245== by 0x1092A9: main (recover.c:48)
==34245==
==34245== LEAK SUMMARY:
==34245== definitely lost: 0 bytes in 0 blocks
==34245== indirectly lost: 0 bytes in 0 blocks
==34245== possibly lost: 0 bytes in 0 blocks
==34245== still reachable: 944 bytes in 2 blocks
==34245== suppressed: 0 bytes in 0 blocks
==34245==
==34245== For lists of detected and suppressed errors, rerun with: -s
==34245== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
My codes below:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// Ensure proper usage
if (argc != 2)
{
printf("Usage: ./recover card\n");
return 1;
}
// If the forensic image cannot be opened for reading, your program should inform the user as much, and main should return 1.
// Remember filenames
char *infile = argv[1];
// Open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
fclose(inptr);
return 1;
}
// block size is 512 bytes
typedef uint8_t BYTE;
int BLOCK_SIZE = sizeof(BYTE) * 512;
BYTE buffer[BLOCK_SIZE];
int index = 0;
FILE *img = NULL;
// The files you generate should each be named ###.jpg, where ### is a three-digit decimal number, starting with 000 for the first image and counting up.
while (fread(buffer, 1, BLOCK_SIZE, inptr) == BLOCK_SIZE)
{
char filename[8];
// is first pic.
if (index == 0) {
sprintf(filename, "%03i.jpg", index);
img = fopen(filename, "w");
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) {
if (img != NULL) {
fwrite(buffer, 1, BLOCK_SIZE, img);
}
index++;
}
} else {
//is not first pic
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) {
//is a new img
//close prev img
if (img != NULL) {
fclose(img);
}
// open a new img
sprintf(filename, "%03i.jpg", index);
img = fopen(filename, "w");
fwrite(buffer, 1, BLOCK_SIZE, img);
index++;
} else {
//keep writing
fwrite(buffer, 1, BLOCK_SIZE, img);
}
}
//Your program, if it uses malloc, must not leak any memory.
}
if (img != NULL) {
fclose(img);
}
fclose(inptr);
return (0);
}
There are some problems in the code:
"rb"
or "wb"
.fopen
fails and returns NULL
, you must not call fclose(inptr);
index
is not incremented and the in next iteration you will reopen the same file without an intervening fclose()
and keep doing this for each block until a JPG signature is found. The memory allocated by fopen()
is lost, which explains the valgrind output. You should only create the file when you find a signature.Here is a modified version:
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
// Ensure proper usage
if (argc != 2) {
fprintf(stderr, "Usage: ./recover card\n");
return 1;
}
// If the forensic image cannot be opened for reading, your program should inform the user as much, and main should return 1.
// Remember filenames
char *infile = argv[1];
// Open input file
FILE *inptr = fopen(infile, "rb");
if (inptr == NULL) {
fprintf(stderr, "Could not open file %s: %s\n", infile, strerror(errno));
return 1;
}
// block size is 512 bytes
enum { BLOCK_SIZE = 512 };
uint8_t buffer[BLOCK_SIZE];
int index = 0;
FILE *img = NULL;
// The files you generate should each be named ###.jpg, where ### is a three-digit decimal number, starting with 000 for the first image and counting up.
while (fread(buffer, 1, BLOCK_SIZE, inptr) == BLOCK_SIZE) {
char filename[20];
//is there is a picture signature, create a new file
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) {
//close prev img if any
if (img != NULL) {
fclose(img);
}
// open a new img
snprintf(filename, sizeof filename, "%03i.jpg", index++);
img = fopen(filename, "wb");
if (img == NULL) {
fprintf(stderr, "Could not open image file %s: %s\n", filename, strerror(errno));
}
}
if (img != NULL) {
// write the block to the current image file
fwrite(buffer, 1, BLOCK_SIZE, img);
}
}
if (img != NULL) {
fclose(img);
}
fclose(inptr);
return 0;
}