0

There are no compile errors just functionality

I was attempting to make a simple XOR crypter in c. I found out that the crypting part is not a problem because when the XOR function is used twice on the same string it returns the the exact string I sent back. The problem I believe is therefore not with the crypting part, I believe that the problem occurs when writing the file.

Function the error is within

int xorFile (char *infile, char *outfile) {
    FILE *in,
         *out;
    long lSize;
    char *buffer;

    in = fopen ( infile , "rb" );
    out = fopen(outfile, "wb");

    if( !in ) perror(infile),exit(1);

    fseek( in , 0L , SEEK_END);
    lSize = ftell( in );
    rewind( in );

    /* allocate memory for entire content */
    buffer = (char*)calloc( 1, lSize+1 );
    if( !buffer ) fclose(in),fputs("memory alloc fails",stderr),exit(1);

    /* copy the file into the buffer */
    if( 1!=fread( buffer , lSize, 1 , in) )
      fclose(in),free(buffer),fputs("entire read fails",stderr),exit(1);

    /* do your work here, buffer is a string contains the whole text */
    int i;
    for(i=0;buffer[i]!='\0';i++) {
        fputc(buffer[i] ^ XOR_KEY,out);
    }
    fclose(in);
    free(buffer);
    fclose(out);
    return 0;

}

What I believe causes the error

int i;
for(i=0;buffer[i]!='\0';i++) {
    fputc(buffer[i] ^ XOR_KEY,out);
}

Full Program

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

#define XOR_KEY 0x6F

int xorFile (char *infile, char *outfile) {
    FILE *in,
         *out;
    long lSize;
    char *buffer;

    in = fopen ( infile , "rb" );
    out = fopen(outfile, "wb");

    if( !in ) perror("blah.txt"),exit(1);

    fseek( in , 0L , SEEK_END);
    lSize = ftell( in );
    rewind( in );

    /* allocate memory for entire content */
    buffer = (char*)calloc( 1, lSize+1 );
    if( !buffer ) fclose(in),fputs("memory alloc fails",stderr),exit(1);

    /* copy the file into the buffer */
    if( 1!=fread( buffer , lSize, 1 , in) )
      fclose(in),free(buffer),fputs("entire read fails",stderr),exit(1);

    /* do your work here, buffer is a string contains the whole text */
    int i;
    for(i=0;buffer[i]!='\0';i++) {
        fputc(buffer[i] ^ XOR_KEY,out);
    }
    fclose(in);
    free(buffer);
    fclose(out);
    return 0;

}

int main (int argc, char *argv[]) {
    if (argc <= 2) {

      fprintf (stderr, "Usage: %s [IN FILE] [OUT FILE]\n" , argv[0]) ;

      exit (1);
    }

    xorFile (argv[1], argv[2]) ;
}

Tested causes

  • Checked on multiple OS's
  • Checked on different file formats
  • Checked on different privileges
  • Checked on different compilers as well(ran out of things to test)

Additional infomation When I encrypted a copy of the source file and decrypted it, all that remained was #include <std

P.Andrews
  • 73
  • 1
  • 14
  • FWIW, I ran your code and it worked fine for me. The output file was exactly the same as the input file. – kaylum Mar 30 '16 at 02:29
  • @TomKarzes: The second part of your question cannot happen. He allocates `lSize+1` with `calloc` (which zeros memory) then only reads `lSize`. The first part of your question is still valid. – Dark Falcon Mar 30 '16 at 02:31
  • What damnt it I don't know why it doesn't work for me in linux and windows. – P.Andrews Mar 30 '16 at 02:31
  • Thanks @TomKarzes any Idea how to fix it. I've got no clue I always use '\0' don't know what to do without it. – P.Andrews Mar 30 '16 at 02:32
  • I replaced my comments with a posted answer, including a more detailed explanation of why it was causing the behavior you observed. – Tom Karzes Mar 30 '16 at 02:52
  • [Don't cast the result of malloc family in C](http://stackoverflow.com/q/605845/995714) – phuclv Mar 30 '16 at 03:19

2 Answers2

2

The problem you're experiencing is caused by your loop exiting prematurely. The following test will stop as soon as it encounters a null byte:

for(i=0;buffer[i]!='\0';i++)

To encrypt the entire file, this needs to be changed to:

for(i=0;i<lSize;i++)

This will be a problem not only for non-text files, but also for decrypting, since the encryption process will introduce zero bytes for any characters that match your XOR_KEY. For instance, if your XOR_KEY is 0x69, which is an ascii 'i', your encrypted file will contain a zero byte in place of each 'i'. When decrypting it, it will cut the file off at the first such character, which explains what you've been seeing. This will correct that.

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
  • Say I create a an obfuscated exe with this. That exe won't be runnable would it? I need a way to decrypt it before running. Am I right? – P.Andrews Mar 30 '16 at 03:00
  • Correct, it almost certainly won't be runnable as long as the key is non-zero. Keep in mind, however, that this encryption is very weak and would be fairly trivial for someone to break. – Tom Karzes Mar 30 '16 at 03:19
1
buffer[i] ^= XOR_KEY;
fputc(buffer[i] ^ XOR_KEY,out);

First, the program looks at the character in buffer[i], XORs it, and stores the XORed character back in buffer[i].

Then, it looks at the character in buffer[i] (which is now XORed), XORs it again, and writes that to out.

So the character that gets written to out has been XORed twice - so it's just the original character.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • Crap thanks for pointing that out. That was a demo to see if it wasn't an output problem, I will change it now. Thanks – P.Andrews Mar 30 '16 at 02:42