XOR failing to decrypt certain files - file

The following code manages to encrypt any file I try, but it only manages to decrypt .txt files. When I try decrypting .mp3, .png, .mp4 files which I have encrypted, it fails to do so.
So I am wondering why this is the case? If it successfully manages to decrypt .txt files, why does it fail to do so with the other file formats I've tried (mentioned before)? Because if I understand XOR encryption correct it returns the original string running it a second time, thus I should be able to reopen the file and it should work normally since the data should be decrypted, r-right?
Feel free to bash me if I am being stupid here.
#include <filesystem>
#include <cstdio>
#include <Windows.h>
int main() {
const std::filesystem::path& path = "folder\\";
FILE* pFile, *pFile1;
char key = '¤';
//get files in dir
for (const std::filesystem::directory_entry &p : std::filesystem::directory_iterator(path)) {
std::filesystem::path filename = p.path().filename();
std::string tmp = path.string() + filename.string();
fopen_s(&pFile, tmp.c_str(), "rb");
if (pFile) {
//for size purposes
char* buffer = 0;
long size;
fseek(pFile, 0L, SEEK_END);
size = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
//rewind(pFile);
buffer = new char[size+1];
//set to zero to remove random chars
memset(buffer, 0, size+1);
//get filecontent
fgets(buffer, size+1, pFile);
fclose(pFile);
//XOR-crypt text/data
for (int i = 0; i < size+1; i++) {
buffer[i] ^= key;
}
//open for writing
fopen_s(&pFile1, tmp.c_str(), "wb");
//write back to file
fputs(buffer, pFile);
fclose(pFile1);
delete[] buffer;
}
}
}

Related

Broken files in C

I made a simple script to rewrite one file contents into another.
Here's code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char filename[1024];
scanf("%s", &filename);
// printf("Filename: '%s'\n", filename);
int bytesToModify; scanf("%d", &bytesToModify);
FILE *fp;
fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
int fSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("%d\n", fSize);
char *buf = malloc(fSize*sizeof(char));
for (int i = 0; i < fSize; i++) {
buf[i] = getc(fp);
}
fclose(fp);
FILE *fo;
fo = fopen("out_file.txt", "w");
for (int i = 0; i < fSize; i++) {
fwrite(&buf[i], 1, 1, fo);
}
fclose(fo);
return 0;
}
Even on small file like this I can see the artifact. Cyrillic sybmol 'я' is coming in the end of file.
If I'll try to rewrite executable file, i get this:
99% of file just turned to these symbols. What is wrong with my code?
I'm using CodeBlocks with GCC Compiler, version 10.1.0.
My Operation System is Windows 10.
Thanks for your help.
You did not open the file in binary mode: "rb" and "wb". Therefore, fgetc will turn all \r\n to a single \n.
For each line terminator there is one character less read. Yet you attempt to read nevertheless, and fgetc will return EOF (and fgetc returns an int, not char). As EOF has value -1 on Windows, when written to file converted to unsigned char this results in Я in the encoding you're using in Notepad (most likely Windows-1251).
Furthermore, since you're using fwrite, then you could similarly use fread. And no need to read, write the characters one at a time, just use
char *buf = malloc(fSize);
int bytesRead = fread(buf, 1, fSize, fp);
fclose(fp);
and
int bytesWritten = fwrite(buf, 1, bytesRead, fo);

Copying all file contents into a char array with fread

I'm trying to copy the contents of a file, specifically a PDF file into a character array so that I can send it over the network.
I'm using the fopen with fread for this.
//Get the file path
getFilePath();
//Open the file
fopen_s(&fp, filePath, "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
//allocate memory
buffer = (char*)malloc(sizeof(char)*size);
int charsTransferred = fread(buffer, 1, size, fp);
fclose(fp);
free(buffer);
I have charsTransferred to see how many characters were transferred over by fread. Using size I can tell how many characters should have been moved over, but obviously I'm not getting that many back. Does anyone know what the issue here could be?
There may be a problem in the part of your code you didn't show.
This works:
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
if (fopen_s(&fp, "somepdfile.pdf", "rb"))
{
printf("Failed to open file\n");
exit(1);
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
rewind(fp);
char *buffer = (char*)malloc(sizeof(char)*size);
if (!buffer)
{
printf("Failed to malloc\n");
exit(1);
}
int charsTransferred = fread(buffer, 1, size, fp);
printf("charsTransferred = %d, size = %d\n", charsTransferred, size);
fclose(fp);
free(buffer);
}
Firstly you need to open in binary mode if a PDF, which I believe is a binary format. Then the seek end / ftell method tends to fail for very large files, as well as for text files (which have suppressed characters physically on the disk). There isn't a pure ANSI C way of statting a file, but the function stat() is widely avialable, and gives you file size.

Reading hex value from image in C

I'm trying to read the hex values from an image file using C. In Linux, this code works fine, but with Windows it reads only the first 334 bytes and I don't understand why.
The code to read the file is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
void readHexFile(char* path) {
FILE *fp;
if ((fp = fopen (path, "r")) != NULL) {
struct stat st;
stat(path, &st);
int i;
int ch;
for (i = 0; i < st.st_size; i++) {
ch = fgetc(fp);
printf("%x ", ch);
}
fclose(fp);
}
else {
return NULL;
}
}
st.st_size comes from <sys/stat.h> package and contains the right value (the size, in bytes, of the image file)
This image show what my program outputs, and the actual binary content of the file it is reading:
As you see after the sequence of 17, 18, 19 there is also hex values but my program prints ffffffff repeatedly.
You opened the file in a text mode, and not as binary. Different platforms may behave differently.
In this case, Microsoft Windows decided that this plain text file ends at the first occurrence of Ctrl+Z (0x1A), and returns EOF for all fgetc afterwards.
Explicitly state that you want to open the file as binary:
fp = fopen ("yourfile", "rb");
and the problem goes away.
I think your loop should look like this:
int ch;
while (!feof(fp)) {
ch = fgetc(fp);
printf("%x ", ch);
}
It's completely unclear to me why you are using st.st_size here.
On Windows, the character 0x1A (Ctrl+Z) is the EOF character for text mode; see this question.
If you're reading from a binary file like a JPEG, you should do so with first opening the file as binary (fopen mode "rb"), then fread into a pre-allocated buffer, the size of which you would determine with ftell with the file pointer at the end of the file:
size_t i, len;
char *buffer = NULL;
fp = fopen(argv[1], "rb");
if(!fp)
// handle error
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
buffer = malloc(len + 1);
if(!buffer)
// handle error
fread(buffer, 1, len, fp);
for(i = 0; i < len; i++)
{
printf("%.2X ", buffer[i]);
}
free(buffer);
buffer = NULL;

Reverse file text

I'm trying to make a program that uses fgets to take the text from a preexisting file, invert it and then write it to another file. This is the code I've written so far:
#include <stdio.h>
#include <string.h>
int main()
{
int c, d;
FILE *file1, *file2;
char string [100], *begin, *end, temp;
file1 = fopen("StartingFile.txt", "rt");
if (file1 == NULL)
{
printf ("Error - Couldn't open file\n");
return (-1);
}
fgets(string, 100, file1);
fclose (file1);
begin = string;
end = begin + strlen(string) - 1;
while (end > begin)
{
temp = *begin;
*begin = *end;
*end = temp;
++begin;
--end;
}
file2 = fopen("FinalFile.txt", "wt");
fprintf (file2, "%s", string);
fclose (file2);
printf ("%s\n", string);
return 0;
}
It works fine if the text in the preexisting file is all in one line, but if it has more than one line, only the first one is inverted and written to the new file. I think that fgets can only read one line, so I think I'll have to use a loop, but I'm having trouble implementing it. Can someone give me a hand? Thanks in advance!
To read each line separately from file use fgets in while loop as below,
while(fgets(string, sizeof(string), file1) != NULL)
{
...
}
fclose(file1);
Inside the loop operate on each line to reverse it.
Your code has quite a few logical errors in it. I would recommend using other f* methods instead.
If you want an easy solution, open the file, determine its length, create two buffers of the size of the file, fill the first buffer with the file's contents and then do a loop to copy the reverse to the other buffer, then write that buffer back. Roughly that would look like this:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *file;
file = fopen("StartingFile.txt", "rt");
if (file == NULL)
{
printf ("Error - Couldn't open file\n");
return (-1);
}
fseek(file, 0, SEEK_END); // move file pointer to end of file
long size = ftell(file); // file pointer position == character count in file
fseek(file, 0, SEEK_SET); // move back to beginning of file
char* buffer = malloc(size * sizeof(char));
fread(buffer, sizeof(char), size, file) // read file contents to buffer
for(long i = 0; i < size/2; ++i)
{
buffer[i] = buffer[size-i-1];
}
fseek(file, 0, SEEK_SET); // The fread set the file pointer to the end so we need to put it to the front again.
fwrite(buffer, sizeof(char), size, file); // Write reverted content
delete buffer;
fclose (file);
}
I haven't tested it and it may contain a few errors since I haven't programmed in C for some time. The only reason to still be programming in C anyways is efficiency and if you want your program to be efficient, the two buffer solution isn't the best either. At least not in terms of memory usage.
I highly recommend getting familiar with all the functions available in C (stdio and so on) cplusplus.com is a great reference for that.
Regards, Xaser

How to create an exact copy of file in c

I want to create an exact copy of a file(.bmp) in c
#include<stdio.h>
int main()
{
FILE *str,*cptr;
if((str=fopen("org.bmp","rb"))==NULL)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
if((cptr=fopen("copy.bmp","wb"))==NULL)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
fseek(str, 0, SEEK_END);
long size=ftell(str);
printf("Size of FILE : %.2f MB \n",(float)size/1024/1024);
char b[2];
for(int i=0;i<size;i++)
{
fread(b,1,1,str);
fwrite(b,1,1,cptr);
}
fseek(cptr, 0, SEEK_END);
long csize=ftell(str);
printf("Size of created FILE : %.2f MB \n",(float)csize/1024/1024);
fclose(str);
fclose(cptr);
return 0;
}
Although it creates a file of the same size but windows throws an error while trying to view the newly created copy of bitmap.
Why is this happening?
You have moved the file pointer for the input file to the end of the file before you start reading it. You need to restore it to the beginning.
Change:
fseek(str, 0, SEEK_END);
long size=ftell(str);
to:
fseek(str, 0, SEEK_BEGIN);
long size=ftell(str);
fseek(str, 0, SEEK_SET);
Note that your code is devoid of error checking - if you had at least checked the result of fread then your mistake would have been immediately apparent. Take-home message: don't cut corners when it comes to error-checking - it will pay dividends later.
You need to seek back to the start of the original file because you are continually reading at the EOF and therefore not making a copy of the file contents, just whatever happens to be in your b[] array.
You are not checking the return codes of fread() and fwrite(). If you had been doing that you might have solved this problem from the return codes.
If you check the size of the original file and the copy in bytes, it should tell you the issue.
This code reads a byte and writes a byte.
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define KB 1024
int main()
{
unsigned int ifd,ofd,rcnt;
char buf[KB];
ifd=open("orig.jpg",O_RDONLY);
if(ifd==0)
{
fprintf(stderr,"Cannot read file\n");
//return 1;
}
ofd=open("copy.jpg",O_WRONLY|O_CREAT);
if(ofd==0)
{
fprintf(stderr,"Cannot open output file\n");
//return 1;
}
while(rcnt=read(ifd,buf,KB))
write(ofd,buf,rcnt);
}
~
This is a nice function to copy files! Copy char by char is better than read the whole file because that result (if the file is to long) is a bufferoverflow!
double copy(char *input, char *output) {
FILE *f_in = fopen(input, "r");
FILE *f_out = fopen(output, "a");
if (!f_in || !f_out) {
fclose(f_in);
fclose(f_out);
return -1;
}
int c;
while ((c = fgetc(f_in)) != EOF)
fputc(c, f_out);
fclose(f_in);
fseek(f_out, 0, SEEK_END);
long size = ftell(f_out);
fclose(f_out);
return (double)(size / 1024 / 1024); // MB
}
This function returns the MB of the output file. If it wasn't successfully it return 0.
Use this function like this:
double output;
if ((output = copy("What ever you want to copy", "Where ever it should be printed")) != -1)
printf("Size of file: %lf MB.\n", output);
Hope this will help :)
I copped your first code and also used first solution just you need to add this code to your program :fseek(str, 0, SEEK_SET);and done your copy bitmap will be produce.

Resources