Cant edit a binary program using fwrite and writing an int? - c

I'm trying to make a program to write a number into two different file(binary elf file) offsets using fwrite and fseek but both seems to report writing and seeking correctly but objdump -s 0x2db0 -n 0x16 testseems to show no change. fwrite and fseek called as:
error = fwrite((void*)&value, sizeof(value), 1, file);
seek_error = fseek(file, offset, SEEK_SET);
whole program is executed like bellow and is supposed to write 0x119e at offset 0x2db0 and 0x01:
./patch test 0x01 0x2db0 0x119e
so instead of seeing 119e at both offsets when running objdump no change seems to happen at all.
whole Source code is:(mostly checking for functions return values)
#include <stdio.h>
#include <stdlib.h>
#include <zconf.h>
#include <errno.h>
int main(int argc, char *argv[]){
long error, seek_error;
long value, offset;
if (argc < 5){
fprintf(stderr, "Incorrect arg number\n");
exit(1);
}
FILE* file = fopen(argv[1], "ab");
if (file == NULL){
fprintf(stderr, "Error openning File\n");
perror("fopen() :");
exit(1);
}
printf("\t\t File opened successfully\n");
value = strtol(argv[4], NULL, 16); /* convert target value to int */
if (value == LONG_MIN || value == LONG_MAX){
fprintf(stderr, "Error calling strtol\n");
perror("strtol() :");
exit(1);
}
offset = strtol(argv[2], NULL, 16);
printf("offset is %ld\n", offset);
if (offset == LONG_MIN || offset == LONG_MAX) {
fprintf(stderr, "Error calling strtol during offset\n");
perror("strtol() :");
exit(1);
}
seek_error = fseek(file, offset, SEEK_SET); /* From start go to end*/
if (seek_error != 0){
fprintf(stderr, "Error calling fseek\n");
perror("fseek(): ");
exit(1);
}
printf("File position is: 0x%lx\n", ftell(file));
error = fwrite((void*)&value, sizeof(value), 1, file);
if (error != 1){
fprintf(stderr, "Error calling write\n");
perror("write() :");
exit(1);
}
printf("Number of bytes written %ld\n", error);
offset = strtol(argv[3], NULL, 16);
printf("offset is %ld\n", offset);
if (offset == LONG_MIN || offset == LONG_MAX) {
fprintf(stderr, "Error calling strtol during scond offset\n");
perror("strtol() :");
exit(1);
}
seek_error = fseek(file, offset, SEEK_SET); /* Seek to the new offset */
if (seek_error != 0){
fprintf(stderr, "Error calling second fseek\n");
perror("fseek(): ");
exit(1);
}
printf("File position is: 0x%lx\n", ftell(file));
error = fwrite((void*)&value, sizeof(value), 1, file);
if (error != 1){
fprintf(stderr, "Error calling write\n");
perror("write() :");
exit(1);
}
printf("Number of bytes written %ld\n", error);
fflush(file); /* flush changes not nesessecarly */
error = fclose(file);
if (error != 0){
fprintf(stderr, "error closing file\n");
perror("close() :");
exit(1);
}
}

You're opening the file in append mode with fopen(argv[1], "ab"). So all writes are done at the end of the file, ignoring the position you seeked to.
Use fopen(argv[1], "rb+") instead. r means to open it in read mode, so the file isn't emptied first, and + means that writing is also allowed.

Related

C programming, copying from one file to another using command line arguments

This is my code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("Missing arguments\n");
return -1;
}
// Check if buffer is valid before reading anything
int bufferSize = atoi(argv[3]);
if (!bufferSize || bufferSize < 1) {
printf("Invalid buffer size\n");
return -1;
}
printf("*** Copying from '%s' to '%s' (Buffer size: %dB) ***\n",
argv[1], argv[2], bufferSize);
// READ SOURCE FILE
FILE *inputFile = fopen(argv[1], "r");
if (!inputFile) {
printf("Error opening source file\n");
return -1;
}
// READ DESTINATION FILE
FILE *outputFile = fopen(argv[2], "w");
if (!outputFile) {
printf("Error opening destination file\n");
return -1;
}
int buffer[bufferSize];
int bytes;
do {
bytes = fread(buffer, 1, bufferSize, inputFile);
if (fwrite(buffer, 1, bytes, outputFile) != bytes) {
printf("Error writing into destination file\n");
return -1;
}
} while (bytes > 0);
fclose(inputFile);
fclose(outputFile);
return 0;
}
But when I try to exe the file it doesn't work. What could be the problem?
Here's the command line:
/Users/jurajc/Documents/Program/C/L1\ 1/C_program/c_program file.txt fileCopy.txt 512
*** Copying from 'file.txt' to 'fileCopy.txt' (Buffer size: 512B) ***
Error opening source file
The input file file.txt cannot be opened: either because it is not present in the current directory or because you do not have read access to it.
You should output more informative error messages. Note also these problems:
if (!bufferSize || bufferSize < 1) is a redundant test. if (bufferSize < 1) is sufficient.
the error messages should be output to stderr
the files should be open in binary mode to reliably copy all file types on legacy systems.
the read/write loop is incorrect: you should stop when fread returns 0 before attempting to write 0 elements to the output file.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 4) {
fprintf(stderr, "Missing arguments\n");
return -1;
}
// Check if buffer is valid before reading anything
int bufferSize = atoi(argv[3]);
if (bufferSize < 1) {
fprintf(stderr, "Invalid buffer size: %s\n", argv[3]);
return -1;
}
printf("*** Copying from '%s' to '%s' (Buffer size: %dB) ***\n",
argv[1], argv[2], bufferSize);
// READ SOURCE FILE
FILE *inputFile = fopen(argv[1], "rb");
if (!inputFile) {
fprintf(stderr, "Error opening source file %s: %s\n",
argv[1], strerror(errno));
return -1;
}
// READ DESTINATION FILE
FILE *outputFile = fopen(argv[2], "wb");
if (!outputFile) {
fprintf(stderr, "Error opening destination file %s: %s\n",
argv[2], strerror(errno));
return -1;
}
int buffer[bufferSize];
int bytes;
while ((bytes = fread(buffer, 1, bufferSize, inputFile)) != 0) {
if (fwrite(buffer, 1, bytes, outputFile) != bytes) {
fprintf(stderr, "Error writing into destination file: %s\n", strerror(errno));
return -1;
}
}
fclose(inputFile);
fclose(outputFile);
return 0;
}

update file based on a key in C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main ()
{
FILE *outfile;
// open file for writing
outfile = fopen ("ads.txt", "a");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
struct person input1 = {"runner", "100", "4376482682"};
//struct person input2 = {"maze", "300", "3232365436"};
// write struct to file
fwrite (&input1, sizeof(struct person), 1, outfile);
//fwrite (&input2, sizeof(struct person), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
FILE *infile;
struct person input;
infile = fopen ("ads.txt", "r");
if (infile == NULL)
{
fprintf(stderr, "\nError opening file\n");
exit (1);
}
// read file contents till end of file
char name[10] = "maze";
char size[6] = "500";
char timestamp[15] = "437838322";
int remaining_size = 100;
int alreadythere =0;
//unpcoming file size
int incoming_file_size = 200;
int target_file_size_toremove = incoming_file_size - remaining_size;
while(fread(&input, sizeof(struct person), 1, infile)){
if(target_file_size_toremove > 0) {
int x = atoi(input.size);
if(target_file_size_toremove < x) {
strcpy(input.name, name);
strcpy(input.size, size);
strcpy(input.timestamp, timestamp);
}
}else {
if(strcmp(input.name, name) == 0) { // if name is eqUAL
if(strcmp(input.size, size) != 0) {
strcpy(input.size, size);
}
if(strcmp(input.timestamp, timestamp) !=0) {
strcpy(input.timestamp, timestamp);
}
alreadythere = 1;
}
printf ("id = %s name = %s %s\n", input.name,
input.size, input.timestamp);
}
}
if(alreadythere == 0) {
struct person incoming = {name, size, timestamp};
fwrite (&incoming, sizeof(struct person), 1, outfile);
}
// close file
fclose (infile);
return 0;
}
The code is in C language. I want to update the size variable when name is equal to "maze". How I can do it, while reading from file?
first the data that is writing in file is -
runner 100 4376482682
maze 300 3232365436
After updating -
runner 100 4376482682
maze 100 3232365436
size should updated from 300 to 100.
I have fixed a number of small bugs in your code related to opening the file in correct mode and checking if fwrite and fread where successful. Then I added the part you where really asking: update the record "maze".
To update the record, we need to read it, change the value and write it back to the file exactly where we have read it. So before reading a record, we query the current file pointer with ftell and before writing, we call fseek to move the file pointer back to the place we read. A call to fflush (another fseek would do as well) is required so that the next fread take place at the correct position.
For testing, I added a third record after "maze" so that we can see - by looking at the file content - that we don't overwrite data.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{
char name[10];
char size[6];
char timestamp[15];
};
int main()
{
FILE* outfile;
// open file for writing binary
outfile = fopen("ads.txt", "wb");
if (outfile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit(1);
}
struct person input1 = { "runner", "100", "4376482682" };
struct person input2 = { "maze", "300", "3232365436" };
struct person input3 = { "street", "400", "4232365486" };
// write struct to file, checking for success
if ((fwrite(&input1, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input2, sizeof(struct person), 1, outfile) != 1) ||
(fwrite(&input3, sizeof(struct person), 1, outfile) != 1))
printf("error writing file !\n");
else
printf("contents to file written successfully !\n");
// close file
fclose(outfile);
FILE* infile;
struct person input;
// Open for both reading and writing, binary
infile = fopen("ads.txt", "r+b");
if (infile == NULL) {
fprintf(stderr, "\nError opening file for update\n");
exit(1);
}
// read file contents till end of file, update "maze"
while (1) {
long pos = ftell(infile);
if (pos < 0) {
fprintf(stderr, "\nError getting file position\n");
break;
}
if (fread(&input, sizeof(struct person), 1, infile) != 1)
break;
// update the value of size here, if name is equal to "maze"
printf("id = %s name = %s %s\n", input.name, input.size, input.timestamp);
if (strcmp(input.name, "maze") == 0) {
if (fseek(infile, pos, SEEK_SET) != 0) {
fprintf(stderr, "\nError moving file pointer\n");
break;
}
strcpy(input.size, "100");
if (fwrite(&input, sizeof(struct person), 1, infile) != 1) {
fprintf(stderr, "\nError writing file\n");
break;
}
// fflush() is required so that fread() take place a the correct position
if (fflush(infile) != 0) {
fprintf(stderr, "\nError flushing file\n");
break;
}
printf(" Updated id = %s name = %s %s\n", input.name, input.size, input.timestamp);
// Since this code update a single record, we could break the loop
}
}
// close file
fclose(infile);
return 0;
}

ssh_scp_read returns garbage

I'm trying to download a file from my server; both the client and the server are Linux, yet ssh_scp_read() returns an incorrect integer. According to the documentation the function writes up to 65536 bytes, yet is only reading 16384 when the file is 37980, but that's not my main concern; near the end of this 16384 bytes it starts to fill the buffer with NULL garbage, that will then be written to the file.
The creation of recursive directories works fine; the problem is downloading files larger than 16384 bytes. At this point I'll use sftp instead of scp, but I would like to know what I am doing wrong.
This is the function code:
int get(ssh_session gno_ses,ssh_scp scp)
{
int rc;
int size, permissions;
char *buff, *filename, path[PATH_MAX];
while(1)
{
rc = ssh_scp_pull_request(scp);
switch (rc)
{
// cases [...]
case SSH_SCP_REQUEST_NEWFILE:
size = ssh_scp_request_get_size(scp);
printf("Size is %d\n",size);
filename = strdup(ssh_scp_request_get_filename(scp));
permissions = ssh_scp_request_get_permissions(scp);
FILE *file;
file = fopen(filename, "w+");
if (!file)
{
ssh_scp_deny_request(scp,"Unable to open");
fprintf(stderr, " %s: %s\n", filename, strerror(errno));
fclose(file);
break;
}
buff = malloc(size);
printf("Size of buffer is %d\n", size);
if (!buff)
{
fprintf(stderr, "\nBuff memory allocation error.\n");
return SSH_ERROR;
}
if( ssh_scp_accept_request(scp) != SSH_OK)
{
fprintf(stderr, "Error accepting request: %s\n", ssh_get_error(gno_ses));
break;
}
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
break;
}
if (fwrite(buff, 1, size, file) != size)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
} while (rc != 0);
fclose(file);
free(filename);
free(buff);
break;
}
}
return SSH_OK;
}
And this is the output:
Size is 37980
Size of buffer is 37980
ssh_scp_read got 16384
ssh_scp_read got 16384
ssh_scp_read got 5212
Error receiving file data: ssh_scp_read called under invalid state
Any input would be appreciated.
The problem was that I was writing size bytes when indeed scp_scp_read() had reported that it had read less than that:
rc = ssh_scp_read(scp, buff, size);
fwrite(buff, 1, size, file)
The fix is to write only rc bytes:
int len_loop = size;
int len;
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR || rc < 0)
{
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(gno_ses));
break;
}
else if (!rc)
{
break;
}
len = fwrite(buff, 1, rc, file);
if (len != rc)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
len_loop -= rc;
} while(len_loop);
change your inner loop as
int len = size;
do
{
rc = ssh_scp_read(scp, buff, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n",
ssh_get_error(gno_ses));
break;
}
if (fwrite(buff, 1, rc, file) != size)
{
perror("Error at writting to file: ");
break;
}
printf("ssh_scp_read got %d\n",rc);
len-=rc;
} while (len);

I am trying to print a txt file and it doesn't work in C homework

I'm writing code that's supposed to verify that a .txt file is a certain format.
I wrote my code as I saw in a tutorial and in the website
and for some reason my program doesn't even print my file.
Can you tell me what I'm doing wrong?
The code will do something far more complex, but I'm still trying to work on my basics.
Here's my code so far:
int main(int argc, char *argv[]) {
/* argv[0] = name of my running file
* argv[1] = the first file that i receive
*/
define MAXBUFLEN 4096
char source[MAXBUFLEN + 1];
int badReturnValue = 1;
char *error = "Error! trying to open the file ";
if (argc != 2) {
printf("please supply a file \n");
return badReturnValue;
}
char *fileName = argv[1];
FILE *fp = fopen(argv[1], "r"); /* "r" = open for reading */
if (fp != NULL) {
size_t newLen = fread(&source, sizeof(char), MAXBUFLEN, fp);
if (ferror(fp) != 0) {
printf("%s %s", error, fileName);
return badReturnValue;
}
int symbol;
while ((symbol = getc(fp)) != EOF) {
putchar(symbol);
}
printf("finish");
fclose(fp);
}
else {
printf("%s %s", error, fileName);
return badReturnValue;
}
}
I think you need a bit more explanations:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// there might be a macro BUFLEN defined in stdio
// which size is optimized for reading in chunks.
// Test if avaiable otherwise define it
#ifndef BUFLEN
# define BUFLEN 4096
#endif
int main(int argc, char *argv[])
{
char source[BUFLEN];
char *filename;
FILE *fp;
size_t fpread, written;
char c;
int ret_fclose;
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// work on copy
filename = malloc(strlen(argv[1]) + 1);
if (filename == NULL) {
fprintf(stderr, "Allocating %zu bytes failed\n", strlen(argv[1]) + 1);
exit(EXIT_FAILURE);
}
filename = strcpy(filename, argv[1]);
// try to open the file at 'filename'
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Opening file \"%s\" filename failed\n", filename);
// errno might got set to something usable, check and print
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// You have two options here. One is to read in chunks of MAXBUFLEN
while ((fpread = fread(&source, 1, BUFLEN, fp)) > 0) {
// Do something with the stuff we read into "source"
// we do nothing with it here, we just write to stdout
written = fwrite(&source, 1, fpread, stdout);
// you can use 'written' for error check when writing to an actual file
// but it is unlikely (but not impossible!) with stdout
// test if we wrote what we read
if ((fpread - written) != 0) {
fprintf(stderr, "We did not write what we read. Diff: %d\n",
(int) (fpread - written));
}
}
// fread() does not distinguish between EOF and error, we have to check by hand
if (feof(fp)) {
// we have read all, exit
puts("\n\n\tfinish\n");
// No, wait, we want to do it again in a different way, so: no exit
// exit(EXIT_SUCCESS);
} else {
// some error may have occured, check
if (ferror(fp)) {
fprintf(stderr, "Something bad happend while reading \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
}
// the other way is to read it byte by byte
// reset the filepointers/errors et al.
rewind(fp);
// rewind() should have reseted errno, but better be safe than sorry
errno = 0;
printf("\n\n\tread and print \"%s\" again\n\n\n\n", filename);
// read one byte and print it until end of file
while ((c = fgetc(fp)) != EOF) {
// just print. Gathering them into "source" is left as an exercise
fputc(c, stdout);
}
// clean up
errno = 0;
ret_fclose = fclose(fp);
// even fclose() might fail
if (ret_fclose == EOF) {
fprintf(stderr, "Something bad happend while closing \"%s\"\n", filename);
if (errno != 0) {
fprintf(stderr, "Error: %s\n", strerror(errno));
}
exit(EXIT_FAILURE);
}
// The macros EXIT_FAILURE and EXIT_SUCCESS are set to the correct values for
// the OS to tell it if we had an eror or not.
// Using exit() is noot necessary here but there exits teh function atexit()
// that runs a given function (e.g: clean up, safe content etc.) when called
exit(EXIT_SUCCESS);
}
You read from the file twice but only print once.
If the file is to small the first reading will read all of the contents, and the second reading will not produce anything so you don't print anything.
I believe you have to reset the pointer after using fread.
Try fseek(fp, SEEK_SET, 0) to reset the pointer to the beginning of the file. Then print the file.

C: OpenSSL RSA_private_decrypt() fails with "error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error”

I'm new with cryptography, so I decided to create simple program that would open a file encrypt data, put it in etest.txt, then open this file decrypt it and put it indetest.txt.I know it sounds really weired but its for educational purposes. so here is my code. I've read many topics about this problem but none of them worked for me.
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
int main(void) {
size_t pri_len; // Length of private key
size_t pub_len; // Length of public key
char *pri_key; // Private key
char *pub_key; // Public key
char *msg = malloc(256); // Message to encrypt
char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message
char *err; // Buffer for any error messages
size_t red;
RSA *keypair = RSA_generate_key(2048, 3, NULL, NULL);
FILE *in = fopen("test.txt", "r");
FILE *out = fopen("etest.txt", "w");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
encrypt = malloc(RSA_size(keypair));
for(;;)
{
red = fread(msg, 1, RSA_size(keypair)-42, in);
if((RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
}
if(fwrite(encrypt, 1, strlen(encrypt), out) == 1)
{
printf("fwrite Error is %d (%s).\n", errno, strerror(errno));
}
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
in = fopen("etest.txt", "r");
out = fopen("dtest.txt", "w");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
decrypt = malloc(RSA_size(keypair));
for(;;)
{
red = fread(msg, 1, 256, in);
if(RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error decrypting message: %s\n", err);
}
fwrite(decrypt, 1, strlen(decrypt), out);
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
RSA_free(keypair);
return 0;
}
When I run code it gives me back error saying:Error decrypting message: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error Sorry if my question sound silly. Hope you can help. Thanks.
There are a few errors here. First when you're reading and encrypting:
red = fread(msg, 1, RSA_size(keypair)-42, in);
if((RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
A call to fread won't necessarily read the number of bytes asked for, and could return 0. So when you reach the end of the file, you man be encrypting more bytes than you need. So pass in red for the number of bytes to encrypt. Also, first check if red is 0 and if so break out of the loop:
red = fread(msg, 1, RSA_size(keypair)-42, in);
if (red == 0) break;
if(((red=RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING))) == -1) {
Note that we're saving the return value of RSA_public_encrypt. That comes into play here where you're writing the encrypted data to disk:
if(fwrite(encrypt, 1, strlen(encrypt), out) == 1)
encrypt is an array of characters, not a string. This means it's not NULL terminated, and it might contain NULL bytes. So you can't use strlen. Instead, capture the return value of RSA_public_encrypt and pass that as the size to write:
if(fwrite(encrypt, 1, red, out) == 1)
Because we're checking the return value of fread to break out of the loop, this isn't needed:
if(feof(in))
{
break;
}
See this post regarding the perils of using feof.
Then there's this when you're reading back the encrypted data:
red = fread(msg, 1, 256, in);
if(RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
RSA_private_decrypt expects a single encrypted block whose length is RSA_size(keypair). So read in that many bytes from disk and pass in that many bytes to the function. Also, check the return value of fread and break out if you don't get the expected amount, and capture the return value of RSA_private_decrypt:
red = fread(msg, 1, RSA_size(keypair), in);
if (red < RSA_size(keypair)) break;
if((red=RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
Later when you write the decrypted data to disk:
fwrite(decrypt, 1, strlen(decrypt), out);
While what was decrypted is probably a string (if your input file was plain text), the returned data is not NULL terminated, so explicitly write than many bytes instead of using strlen:
fwrite(decrypt, 1, red, out);
Finally, as with the encryption loop, this is not needed in the decryption loop:
if(feof(in))
{
break;
}
With these fixes applied, you should get the expected results.

Resources