0

My code looks right, and after some segmentation errors, I finally fixed that, but I've run into a problem: My created ###.jpg files don't actually seem to be written to anywhere, as in I can't find them? This is confirmed when check50 can't find them. Debug50 didn't help and trying to use printf and fgetc didn't work because typing in 001.jpg wasn't an acceptable file type?

So why won't my newly created jpgs go anywhere?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    // ensure one command-line argument
    if (argc != 2)
    {
        printf("Input: One Forensic Image File\n");
        return 1;
    }
    
    // open and read file to file pointer
    FILE* forensic = fopen(argv[1], "r");
    // trying to open file
    if (forensic == NULL)
    {
        printf("Could not open file\n");
        return 1;
    }
    
    FILE* img = NULL;
    
    int size = (512 * sizeof(int));
    int found = 0;
    int bytes_read;
    int *block = malloc(size);
    
    while (fread(block, size, 1, forensic) == 1)
    {
        char filename[8];
        
        // read file
        fread(block, size, 1, forensic);
        
        // JPEG?
        if (block[0] == 0xff && block[1] == 0xd8 && block[2] == 0xff && (block[3] & 0xf0) == 0xe0)
        {
            // if conditions are met for new jpg, and no previous jpg has been detected, open up new ###.jpg for first time
            if (found == 0)
            {
                sprintf(filename, "000.jpg");
                img = fopen(filename, "w");
                fwrite(block, size, 1, img);
                fclose(img);
            }
            // if conditions are met for new jpg at beginning of block, open new jpg
            else;
            {
                sprintf(filename, "%03i.jpg", found);
                img = fopen(filename, "w");
                fwrite(block, size, 1, img);
                fclose(img);
            }
            found++;
        }
        
        // if it isn't a new jpg but there has already been a jpg in the file, then append to previously open jpg (called filename)
        else if ((block[0] != 0xff || block[1] != 0xd8 || block[2] != 0xff || (block[3] & 0xf0) != 0xe0) && (found > 0))
        {
            img = fopen(filename, "a");
            fwrite(block, size, 1, img);
            fclose(img);
        }
    }

    // free mallocs and close open files
    fclose(forensic);
    free(block);
}
0

The files can't be found because they are never being opened or created.

I saw about 3 issues. Most important, block is declared as a pointer to type int. It should be a pointer to an unsigned byte type such as uint8_t. That's wreaking havoc on the code and causing the data not to be handled correctly. Most importantly, it means that the signature block is never being seen, so the code to create files is never executed.

Next, there's this:

    int size = (512 * sizeof(int));

It's setting size to 512 * 8 or 4 kb. Way too large.

Finally, this code will skip half the data because it has two fread statements back to back.

This should get you going.

Bonus tip: The final if statement will not produce the results you think. just flipping == to != in a complex logic test does not flip the entire test. Think about it. If the first byte were 0xff just by coincidence, there wouldn't be a signature but the data block wouldn't be processed. In this case, a simple else would work (without the if) because it's a binary choice. It either IS a signature block (detected by the first if statement) or it isn't. There's no need to test that it isn't

For future reference, if you want to negate or reverse a complex logic test like this, just enclose the whole test in parentheses and put a not operator, !, in front of it. if( ! (complex-logic-test-here) )

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

5
  • Thank for the help! I got it to work, but I still have two questions: 1. Why did I need uint8_t and not int *? 2. Why didn't I need the second fread()? The first fread() was just a condition to see if I was at the end of the file. How did it also do the action of reading the file?
    – Matthew
    Jul 6 '20 at 2:14
  • Also: I did need the second else-if, just the only condition was else if (found > 0)
    – Matthew
    Jul 6 '20 at 2:16
  • 1. int will store each item in an 8 byte integer format and will treat it as a signed integer, meaning that anything that starts with a 1 as the first bit gets mishandled when dealing with raw data. 2. The first fread isn't just a test. it actually does the read. When the read is executed, the return value from the fread call is evaluated as the test. So, it both does a read and returns a value to indicate the success or failure of the read.
    – Cliff B
    Jul 6 '20 at 6:09
  • Also, the first if(block[0]...) test is sufficient. The second one, else if ((block[0] != 0xff ||...) is directly paired with the first, so all that's needed is the else clause, not an else if. It's simply impossible for the first 4 bytes to be anything but one of two choices - either it is or it isn't a signature.
    – Cliff B
    Jul 6 '20 at 6:12
  • BTW, I just noticed something. There's an else statement with a semicolon after it. That means that the code inside the curly braces that follow will ALWAYS be executed. You should probably remove that semicolon. Luckily, the code would have worked no matter what with this error, only because it would close and reopen the first file before incrementing the file count.
    – Cliff B
    Jul 6 '20 at 6:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .