为什么这个代码不能生成正确的散列?

时间:2021-10-27 17:06:03

I had to write a tiny decryption program in C to brute force a key from one file, here "resource.bin", and use that one to decrypt another file using DES-EDE, here "rom_dump.bin". The indication for the correct key is that the decrypted file content starts with a ten digit number terminated by \0. After that the decrypted content should be written to another file, here "decrypted.bin" and the file should be hashed with ECDSA (with the function EVP_ecdsa()). All of this is done on SUSE Linux. The files can be found here:

我必须用C语言编写一个小的解密程序,才能从一个文件(这里是“资源”)强制执行一个密钥。用这个来解密另一个使用DES-EDE的文件,这里是“rom_dump.bin”。正确密钥的指示是,解密文件内容以10位数字开头,以\0结尾。在此之后,解密后的内容应该被写入另一个文件,这里是“解密”。bin”和文件应该与ECDSA(使用函数EVP_ecdsa())进行散列。所有这些都是在SUSE Linux上完成的。这些文件可以在这里找到:

https://spideroak.com/browse/share/see/stack/*/

https://spideroak.com/browse/share/see/stack/*/

Now, the decryption works just fine, but the hash value is not correct:

现在,解密工作得很好,但是哈希值不正确:

a493af52c1a000fcace34de8b0a74a9cf9067ffc

a493af52c1a000fcace34de8b0a74a9cf9067ffc

But even after days of searching, I just cannot find the problem. It's probably just something rediculess I'm overseeing but I'd be very glad if somebody could help me out here. Thanks in advance.

但即使经过几天的搜寻,我还是找不到问题。这可能只是我监管的一个问题,但如果有人能帮助我,我会很高兴的。提前谢谢。

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <unistd.h>
#include <fcntl.h>

const unsigned long long bufferSize = 0x10000;

int checkOutput(unsigned char *output) {
    int i = 0;
    for (i; i < 6; i++) {
        if (!isdigit(output[i])) {
            return 0;
        }
    }

    return 1;
}

void changeKey(unsigned char *key, unsigned char *fileContent, long keyLength,
long initVectorLength) {
    int i = 0;
    for (i; i < keyLength + initVectorLength; i++) {
        key[i] = fileContent[i];
    }
}

void toHashFile(FILE *hashFile, unsigned char *hash, int hashLength) {
    int i = 0;
    for (i; i < hashLength; i++) {
        fprintf(hashFile, "%02x", hash[i]);
    }

    fprintf(hashFile, "\n");
}

void toOutputFile(FILE *fileName, unsigned char *output,
int outputLength) {
    int i = 0;
    for (i; i < outputLength; i++) {
        fprintf(fileName, "%c", output[i]);
    }

    fprintf(fileName, "\n");
}

void writeToFile(const unsigned char *fileName, unsigned char *content,
int contentLength,
void (*functionPointer)(FILE *, unsigned char *, int)) {
    FILE *file = fopen(fileName, "w");
    (*functionPointer)(file, content, contentLength);
    fclose(file);
}

void createHash(unsigned char *hash, unsigned char *output, int length,
int *hashLength) {
    EVP_MD_CTX hashContext;
    EVP_MD_CTX_init(&hashContext);
    EVP_DigestInit(&hashContext, EVP_ecdsa());
    EVP_DigestUpdate(&hashContext, output, length);
    EVP_DigestFinal(&hashContext, hash, hashLength);
}

int main() {
    /* output stuff */
    unsigned char keyAndInitVector[24] = {0x00};
    unsigned char output[bufferSize];
    unsigned char outputFinal[bufferSize];
    int outputLength;

    /* determine key length and init vector */
    int initVectorLength = EVP_CIPHER_iv_length(EVP_des_ede_ecb());
    int keyLength = EVP_CIPHER_key_length(EVP_des_ede_ecb());

    /* read resource files */
    unsigned char romFileContent[bufferSize];
    unsigned char resFileContent[bufferSize];
    int romLength = read(open("rom_dump.bin", O_RDONLY), romFileContent,
        bufferSize);
    int resLength = read(open("resource.bin", O_RDONLY), resFileContent,
        bufferSize);

    /* init context */
    EVP_CIPHER_CTX cypherContext;
    EVP_CIPHER_CTX_init(&cypherContext);

    int i = 0, j;
    int isDecrypted = 0;

    for (i; i < romLength - (keyLength + initVectorLength) &&
    !isDecrypted; i++) {
        changeKey(keyAndInitVector, romFileContent + i, keyLength,
            initVectorLength);

        EVP_DecryptInit(&cypherContext, EVP_des_ede_ecb(),
            keyAndInitVector, keyAndInitVector + keyLength);
        EVP_DecryptUpdate(&cypherContext, output, &outputLength,
            resFileContent, resLength);

        for (j = 0; j < resLength; j++) {
            if (checkOutput(output + j) == 1) {
                isDecrypted = 1;
                break;
            }
        }
    }

    if (isDecrypted) {
        int postfixLength;
        EVP_DecryptFinal(&cypherContext, outputFinal,
            &postfixLength);

        writeToFile("decrypted.bin", output,
            outputLength + postfixLength, &toOutputFile);

        int hashLength = 0;
        unsigned char hash[bufferSize];
        createHash(hash, output, outputLength + postfixLength,
            &hashLength);
        writeToFile("hash.txt", hash, hashLength, &toHashFile);
    }

    EVP_CIPHER_CTX_cleanup(&cypherContext);
    return isDecrypted;
}

2 个解决方案

#1


1  

In your toOutputFile() function, you add a \n to your file, but down in the main() you don't hash the file, but the output.

在toOutputFile()函数中,将一个\n添加到文件中,但是在main()中,不是哈希文件,而是输出。

That means, your decrypted.bin has an additional \n which does not exist in your output which is why when hashing the file, the hash will be different from the one you created with that program.

这意味着,你的解密。bin有一个额外的\n,它不存在于您的输出中,这就是为什么当对文件进行散列时,散列将与您使用该程序创建的散列不同。

#2


1  

You fail to concatenate the output and postfix output. When you write the decrypted file and calculate the hash you are working with the first outputLength bytes of output plus postfixLength bytes of garbage.

您未能连接输出和后缀输出。当您编写解密文件并计算散列时,您将使用输出的第一个outputLength字节加上垃圾的postfixLength字节。

Remove the outputFinal array declaration from main and at the end, write:

从main和末尾删除outputFinal数组声明,写:

    if (isDecrypted) {
        int postfixLength;
->        EVP_DecryptFinal(&cypherContext, output + outputLength,
            &postfixLength);

        ...

#1


1  

In your toOutputFile() function, you add a \n to your file, but down in the main() you don't hash the file, but the output.

在toOutputFile()函数中,将一个\n添加到文件中,但是在main()中,不是哈希文件,而是输出。

That means, your decrypted.bin has an additional \n which does not exist in your output which is why when hashing the file, the hash will be different from the one you created with that program.

这意味着,你的解密。bin有一个额外的\n,它不存在于您的输出中,这就是为什么当对文件进行散列时,散列将与您使用该程序创建的散列不同。

#2


1  

You fail to concatenate the output and postfix output. When you write the decrypted file and calculate the hash you are working with the first outputLength bytes of output plus postfixLength bytes of garbage.

您未能连接输出和后缀输出。当您编写解密文件并计算散列时,您将使用输出的第一个outputLength字节加上垃圾的postfixLength字节。

Remove the outputFinal array declaration from main and at the end, write:

从main和末尾删除outputFinal数组声明,写:

    if (isDecrypted) {
        int postfixLength;
->        EVP_DecryptFinal(&cypherContext, output + outputLength,
            &postfixLength);

        ...