C:结构数组字段中的sha256哈希函数输出在将结构内容写入磁盘时导致崩溃

时间:2019-03-17 19:50:39

标签: c pointers struct openssl sha256

我正在尝试编写一个程序,该程序将凭据信息存储在一个结构数组中,然后将该信息打印到文件中(这仅供学习之用,请放心)。为此,我创建了一个结构数组,然后栅格化该数组以将相关信息分配给每个字段。这继续进行没有问题。然后,我尝试再次对数组进行栅格化,以将每个结构的字段写入文件中,从而在第一次写入后程序崩溃(即仅一个结构中有价值的内容已成功写入输出文件)。

我创建了以下简化/精简的程序变体,再现了错误。我认为问题出在set_hash_entry函数之内,因为该错误仅在将该函数重新引入我的精简代码中以代替硬编码测试值后才出现。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/sha.h"
#include <time.h>
#include <math.h>

struct password_struct {
    char password[17];
    char hash[65];
    float entropy;
};

struct password_struct* allocate_heap_memory(int num_passwords);
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs);
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs);
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs);
void set_hash_entry(struct password_struct* user_password_structs);

int main(void) {

    int num_passwords = 2;

    struct password_struct* user_password_structs = allocate_heap_memory(num_passwords);

    struct password_struct* allocated_memory_start_ptr = user_password_structs;

    orchestrate_value_setting(num_passwords, user_password_structs);

    user_password_structs = allocated_memory_start_ptr; // Resetting pointer to allow cycling back through all structures for appending data to output file
    orchestrate_file_output(num_passwords, user_password_structs);

    free(allocated_memory_start_ptr);
}


struct password_struct* allocate_heap_memory(int num_passwords) {

    struct password_struct* user_password_structs = malloc(num_passwords * sizeof(struct password_struct));

    if (!user_password_structs) {
        printf("Malloc failed, exiting\n");
        exit(0);
    }

    return user_password_structs;

}

void set_hash_entry(struct password_struct* user_password_structs){

    int pass_entry_length = strlen(user_password_structs->password);
    SHA256_CTX context;
    unsigned char generated_hash[65]; //sha256 standard digest length + 1;    
    SHA256_Init(&context);
    SHA256_Update(&context, (unsigned char *)user_password_structs->password, pass_entry_length);
    SHA256_Final(generated_hash, &context);

    char* hash_ptr = &user_password_structs->hash[0];

    int i;
    for (i=0; i < (64); i++) {
        snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
    }
    user_password_structs->hash[64] = '\0';
    printf("%s\n", user_password_structs->hash);

}

void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs) {

        char pw1[10] = "test";
        char pw2[10] = "test2";
        float entropy1 = 5.0;
        float entropy2 = 10.0;
        strcpy(user_password_structs->password, pw1);
        set_hash_entry(user_password_structs);
        user_password_structs->entropy = entropy1;
        user_password_structs++;

        strcpy(user_password_structs->password, pw2);
        set_hash_entry(user_password_structs);
        user_password_structs->entropy = entropy2;
        user_password_structs++;


}

void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs) {

    printf("Writing data to disk...\n");

    char file_name[20] = "name";
    int i;
    for (i = 0; i < num_passwords; i++) {
        write_results_to_disk(file_name, user_password_structs);
        user_password_structs++;
    }
}

void write_results_to_disk(char file_name[], struct password_struct* user_password_structs) {

    FILE *file_pointer = fopen(file_name, "a");
    if (file_pointer == NULL) {
        printf("Error: Failed to open file\n");
        exit(1);
    }

    fprintf(file_pointer, "%s:%s:%f\n", user_password_structs->password, user_password_structs->hash, user_password_structs->entropy);
    fclose(file_pointer);


}

运行该程序后,将产生以下输出:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
Writing data to disk...
*** Error in `./diagnostic': free(): invalid next size (normal): 0x0804b0c0 ***
Aborted (core dumped)

我天真的认为这是与我的

有关的溢出问题
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]);

操作,但是增加结构中哈希缓冲区的大小似乎无济于事。任何帮助将不胜感激!

我编译如下:gcc -o diagnostic -g diagnostic.c -lcrypto -lm

1 个答案:

答案 0 :(得分:1)

char hash[65];

好的,hash可以容纳65个字符。

char* hash_ptr = &user_password_structs->hash[0];

因此,hash_ptr指向hash,因此它指向65个字符的空间。

for (i=0; i < (64); i++) {
    snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}

i为60时,i*2为120。因此,您试图写入具有65个字符的空间的缓冲区的第120个位置。

在循环中将(64)更改为32或将hash[65]更改为更大的缓冲区。

使用valgrind立即发现了这一点。您还应该学会使用一些方法来检测缓冲区溢出,释放后使用,双重释放以及类似的问题。