Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does NULL terminating a sha256 hash crash when using dynamic memory but not static memory?

I'm using openssl's libcrypto library to try and create a sha256 hash of a arbitrary input buffer, however when I null terminate the hash buffer to make it a C string it crashes but only when using dynamic memory returned from malloc but not when I use statically allocated memory like in this example: generate sha256 with openssl and C++. I'm allocating 65 bytes just like the example, as shown by the length value being printed. So why does null terminating the buffer crash when using dynamic memory as opposed to static memory?

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

static int sha256(char *in, char **out)
{
    int rtrn, i;
    SHA256_CTX sha256;
    unsigned char hash[SHA256_DIGEST_LENGTH];

    rtrn = SHA256_Init(&sha256);
    if(rtrn < 0)
    {
        printf("Sha Init Error\n");
        return -1;
    }

    rtrn = SHA256_Update(&sha256, in, strlen(in));
    if(rtrn < 0)
    {
        printf("Sha Update Error\n");
        return -1;
    }

    rtrn = SHA256_Final(hash, &sha256);
    if(rtrn < 0)
    {
        printf("Sha Final Error\n");
        return -1;
    }

    *out = malloc((SHA256_DIGEST_LENGTH * 2) + 1);
    if(*out == NULL)
    {
        printf("Can't allocate output buf\n");
        return -1;
    }

    for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        sprintf(*out + (i * 2), "%02x", hash[i]);
    }

    printf("Length: %d\n", (SHA256_DIGEST_LENGTH * 2) + 1);

    *out[64] = '\0';

    return 0;
}

int main(void)
{
    int rtrn;
    char *input = "3r98h932hr934hor";
    char *output;

    rtrn = sha256(input, &output);
    if(rtrn < 0)
    {
        printf("Sha256\n");
        return -1;
    }

    printf("%s\n", output);

    return 0;
}
like image 588
2trill2spill Avatar asked Mar 15 '23 08:03

2trill2spill


1 Answers

I suspect this is because you did not mean:

*out[64] = '\0';

but rather:

(*out)[64] = '\0';

Array subscripting ([]) has higher precedence than the indirection (*) operator in C, so what you wrote is the equivalent to:

*(out[64]) = '\0';

which will be corrupting a random area on the stack (where the char ** lives).

like image 120
abligh Avatar answered Mar 17 '23 16:03

abligh