c - C:将结构内容写入磁盘时,结构数组的字段中的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
解决方案
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。所以你试图写入缓冲区的第 120 个位置,有 65 个字符的空间。
将其更改(64)
为32
循环或更改hash[65]
为更大的缓冲区。
使用valgrind
立即发现了这一点。你也应该学会使用一些检测缓冲区溢出、释放后使用、双重释放和类似问题的工具。