0

The code manages to identify the signature. However, it seems that it reads incorrect amount of bytes, because it's not identified again. Where did I do wrong?

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



int checkSig(FILE* intpr,unsigned char* firsts,unsigned char* signature); // check for jpeg signature

int main(int argc, char* argv[])
{


    char* Source = "card.raw"; // source file, raw data
    FILE* intpr = fopen(Source,"r");
    FILE* outptr;
    unsigned char* firsts;
    unsigned char signature[] = {0xff,0xd8,0xff}; // first 3 constant bytes of JPEG file signature
    unsigned char* buffer;
    char filename[ sizeof("999.jpg")]; // filename for every exported image
    int c=0,s=0,k=0,f=0,e=0;

    if (intpr == NULL){
        printf("File %s is corrupted",Source);
        return 2;
    }


    firsts = malloc( sizeof(unsigned char) * 4); // buffer for checking signature
    buffer = malloc( sizeof(unsigned char) * 512); 

    while( !feof(intpr) ){
        if (checkSig(intpr,firsts, &signature) == 1){ // checks for signature, return true/false
            f = 1;
            e = 1;
        }
        if (e == 1){ // if first signature found, keep writing to new image file until next signature found
            s = sprintf(filename,"%03d.jpg",k);
            if (s < 0){
                printf("Error creating filename");
                return -1;
            }
            if (f==1){ // if a new signature found, create a new image file
                if (strcmp(filename, "000.jpg") != 0){ //avoid closing the first image file because it has not been created yet.
                    fclose(outptr);
                }

                outptr = fopen(filename,"w");
                if (outptr == NULL){
                    printf("File %s is corrupted",filename);
                    return 2;
                }
                f = 0;
            }
            fread(buffer, sizeof(unsigned char) * 512, 1, intpr);
            fwrite(buffer, sizeof(unsigned char) * 512, 1, outptr);
            k++;
        }


    }

    free(firsts);
    free(buffer);
    fclose(intpr);
    fclose(outptr);

}

/* this function goes every 4 bytes and checks for a specific hex pattern */

int checkSig(FILE* intpr,unsigned char* firsts,unsigned char* signature){
    int c=0;

    if (fread(firsts, sizeof(unsigned char) * 4, 1, intpr) != 1){
        printf("Couldn't read from file");
        return -1;
    }   

    for (int t=0; t < 3 ; t++){
        if (signature[t] == firsts[t]){
            c++;
        }
        if (c == 3){
            if ((firsts[t+1]==0xe0 || firsts[t+1]==0xe1 || firsts[t+1]==0xe2 || firsts[t+1]==0xe3 || firsts[t+1]==0xe4 || firsts[t+1]==0xe5 || firsts[t+1]==0xe6 || firsts[t+1]==0xe7 || firsts[t+1]==0xe8 || firsts[t+1]==0xe9 || firsts[t+1]==0xea || firsts[t+1]==0xeb || firsts[t+1]==0xec || firsts[t+1]==0xed || firsts[t+1]==0xee || firsts[t+1]==0xef))
                    c++;
        }
    }
    if (c==4){
        fseek(intpr, sizeof(unsigned char) * -4, SEEK_CUR);
        return 1;
    }
    else{
        return 0;
    }

}
1

One thing not accounted for in this design is the possibility of finding a "false jpg sig" in the middle of a 512-byte block. Recall from the spec:

Thanks to FAT, you can trust that JPEGs' signatures will be "block-aligned." That is, you need only look for those signatures in a block’s first four bytes.

Think "greedy". Since the sigs are "block-aligned", a better approach would be to read the raw file in 512-byte blocks.

Let's imagine a card.raw with 1 "junk" block and 3 jpgs that looks something like this: ([blah] is any 4 bytes, [sig ] is a 4byte jpg signature)

[blah] [sig ] [blah].....to 512.....[blah]
[sig ] [blah] [blah].....to 512 ....[blah]
[sig ] [blah] [blah].....to 512 ....[blah]
[sig ] [blah] [blah].....to 512 ....[blah]

The first checkSig returns 0, file pointer is at 4th byte.. The second checkSig returns 1. Where is the file pointer? At the 5th byte. So fread(buffer, sizeof(unsigned char) * 512, 1, intpr); starts reading at the 5th byte. It will never find a jpg sig.

6
  • Thank you for replying. I used fread with the size 512, isn't that 512-byte block?
    – Cstudent
    Jan 9 '17 at 14:33
  • What about the checkSig function? Jan 9 '17 at 14:40
  • After the first signature is found, it's used after each 512-bytes to check the first 4 bytes of the next block.
    – Cstudent
    Jan 9 '17 at 15:08
  • Hopefully the edited answer clarifies. Jan 9 '17 at 15:25
  • Thanks again for elaborating, but I thought that fseek(intpr, sizeof(unsigned char) * -4, SEEK_CUR); deals with that problem. It should return file's pointer backwards to the beginning of the signature.
    – Cstudent
    Jan 9 '17 at 16:04

You must log in to answer this question.

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