【问题标题】:Problems with C XOR executable file encryption / decryptionC XOR 可执行文件加密/解密的问题
【发布时间】:2018-01-08 14:35:06
【问题描述】:

我正在尝试在 C 中为 .exe 文件创建一个简单的 XOR 加密器/解密器。我还是 C 的新手,还不了解所有内容,尤其是内存方面的东西。所以我一直在关注一个关于如何制作一个简单的 XOR 字符串加密器的在线教程,它工作得很好。现在我想修改它,以便我可以加密/解密可执行文件,并决定使用 fwrite() 和 fread() 函数。这是我想出的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // execve function

#define XOR_KEY 0xAA // key

#define JOB_CRYPT 1 // alter flow depending on the job
#define JOB_DECRYPT 2


//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

    void xorFile (char *infile, char *outfile) {

        FILE *nFile, *eFile;

        long nFileSize; // store file size of the file we want to read

        char *buffer; // buffer for reading
        char *eBuffer; // buffer for storing encrypted data

        size_t rResult;
        size_t wResult;

        ///// READ FILE /////

        nFile = fopen(infile, "rb");

        if(nFile == NULL) {

            fputs("Error opening file...", stderr);
            exit(EXIT_FAILURE);

        }

        fseek(nFile, 0, SEEK_END);
        nFileSize = ftell(nFile);
        rewind(nFile);

        buffer = (char *) malloc(sizeof(char) * nFileSize);

        if(buffer == NULL) {

            fputs("Error allocating memory...", stderr);
            exit(EXIT_FAILURE);

        }

        rResult = fread(buffer, 1, nFileSize, nFile);

        if(rResult != nFileSize) {

            fputs("Error reading file...", stderr);
            exit(EXIT_FAILURE);

        }

        fclose(nFile);

        printf("File size is: %ld\n", nFileSize);
        printf("Buffer size is (pointer): %u\n", sizeof(buffer));
        printf("Reading result: %lu\n", rResult);

        ////// WRITE TO FILE //////

        eFile = fopen(outfile, "wb");


        if(eFile == NULL) {

            fputs("Error creating file...", stderr);
            exit(EXIT_FAILURE);

        }

        eBuffer = (char *) malloc(sizeof(char) * nFileSize);

        if(eBuffer == NULL) {

            fputs("Error allocating memory (2)...", stderr);
            exit(EXIT_FAILURE);

        }

        // encrypt byte by byte and save to buffer
        printf("Proceeding with encryption!\n");

        for(int i = 0; buffer[i] != EOF; i++) {

            eBuffer[i] = buffer[i] ^ XOR_KEY;

        }

        printf("Proceeding with fwrite()!\n");

        wResult = fwrite(eBuffer, 1, nFileSize, eFile);

        fclose(eFile);

        printf("eBuffer size is (pointer)%u\n", sizeof(eBuffer));
        printf("Writing result: %lu\n", wResult);

        free(buffer); // free buffers in heap
        free(eBuffer);

    }


//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////


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

    // checking if all parameters were given

    if(argc < 4) {

        fprintf(stderr, "Usage: %s [CRYPT | DECRYPT] [IN-FILE] [OUT-FILE]\n", argv[0]);
        exit(EXIT_FAILURE);

    }

    int job;

    // DOLOCIMO JOB

    if(strcmp(argv[1], "CRYPT") == 0) {

        job = JOB_CRYPT;

    } else if (strcmp(argv[1], "DECRYPT") == 0) {

        job = JOB_DECRYPT;

    } else {

        fprintf(stderr, "Please select [CRYPT | DECRYPT]!");
        exit(EXIT_FAILURE);

    }

    // CRYPT/DECRYPT OUR FILE

    xorFile(argv[2], argv[3]);


    if(job == JOB_DECRYPT) {

        char *args[] = {argv[3], NULL};

        int errExec = execve(args[0], args, NULL);

        if(errExec == -1) {

            perror("Error executing file...");
            exit(EXIT_FAILURE);

        }

    }


    return 0;
}

我很抱歉代码看起来很丑,但我首先想让它工作,稍后我会改进它。

无论如何,当我在命令提示符下运行它时,加密工作正常,它会生成一个加密文件,但是当我运行 decrpytion 作业时,程序 在解密过程中崩溃。这是发生的事情的图片,因此您可以更好地想象它。

由于我的声望少于 10,我不能嵌入图片。 Here is a link to Imgur.

这里出了什么问题?我在解密时是否会造成缓冲区溢出?

谢谢!

【问题讨论】:

  • 它在哪一行崩溃?如果您不知道,请在调试器中单步执行,直到找到为止。
  • buffer[i] != EOF 可能会发生或不会发生,但这不是文件结束的测试。
  • 使用buffer[i] ^= XOR_KEY 你不需要第二个缓冲区
  • @Holger 是的。不知道为什么我没有想到。在这种情况下,问题仍然存在。好的,所以它在读取它时可能不会到达加密的.exe中的EOF。我尝试插入!= nFileSize,所以它会不断重复,直到写入与读取相同数量的字符,现在甚至加密过程都失败了,而不仅仅是解密。
  • @user694733 当涉及到异或的 for 循环时它崩溃了。

标签: c encryption xor


【解决方案1】:

问题来了:

    for(int i = 0; buffer[i] != EOF; i++) {
        eBuffer[i] = buffer[i] ^ XOR_KEY;
    }

二进制文件可以包含任何值的字节。所以EOF 值是有效的并且不指定文件的结尾。这意味着如果文件包含具有此值的字节,则循环将提前退出并且您不会对所有字节进行异或。如果文件不包含此字节,则循环将运行超过分配内存的末尾,该内存调用undefined behavior,在这种情况下表现为崩溃。

你知道你需要处理多少字节,所以用它作为你的循环控制:

    for(int i = 0; i < nFileSize; i++) {

其他一些小的更正:

buffer = (char *) malloc(sizeof(char) * nFileSize);
if(buffer == NULL) {
    fputs("Error allocating memory...", stderr);
    exit(EXIT_FAILURE);
}

Don't cast the return value of malloc。另外,sizeof(char) 的定义是 1,所以你可以忽略它。

另外,如果系统或库函数失败,您应该使用perror 打印错误消息。这将打印有关函数失败原因的附加信息。

buffer = malloc(nFileSize);
if(buffer == NULL) {
    perror("Error allocating memory...");
    exit(EXIT_FAILURE);
}

【讨论】:

  • 将 for 循环更改为 for(int i = 0; i &lt; nFileSize; i++) { ... 会使加密和解密过程现在都失败。两者都在 XOR-ing 上崩溃。
  • @0xd4v3 我使用此更改成功加密和解密。您可能还有其他更改。
  • 天哪,你是对的。我只改变了条件的右侧部分而忘记了左侧部分。我确认for(int i = 0; i &lt; nFileSize; i++) { ... 是正确的解决方案。我想知道为什么我自己没有考虑过... -.- 谢谢。 :) 哦,感谢那些小的更正。
  • 正确的解决方案,但您的解释令人困惑。 EOF 是一个 integer 值,超出单个字节的范围。在扫描字节数组时,很可能会遇到字节值(EOF & 0xFF),它将被扩展为整数值 EOF 进行比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 2015-12-16
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多