Friday, May 17, 2024

Hacking 102 - Leaking the canary with strncpy

Hacking 102 - Leaking the canary with strncpy


A convoluted example of how you can leak GCC's stack protector canary with a strncpy, thanks to strncpy not null terminating when the strlen is greater than or equal to the buffer size specified in the 3rd parameter.

get_canary() just verifies it's actually the same as GCC's canary.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned long get_canary()
{
    asm("mov %fs:0x28, %rax");
}

// prints out our string, which is a non-null terminated string, thanks to strncpy's rule of not null terminating!

void print_str(const char *str)
{
    for (int i = 0; i < strlen(str); i++) {
        printf("%x", (unsigned char) str[i]);
    }

    printf("\n");

    for (int i = 0; i < strlen(str) + 16; i+=8) {
        unsigned long *p = (unsigned long *) &str[i];
        printf("%lx ", *p);
    }

    printf("\n");


    unsigned long *canary = (unsigned long *) &str[256+8];

    printf("Is this the canary getting leaked out? %lx\n", *canary);

    printf("Hint: Ignore the last two hex digits, as that's just 'A' character, overwriting the 0x00 null\n");

}

void func(const char *input)
{
    char buf[256];

    // NB: This is a convoluted strncpy, probably won't find it in the wild, but you never know...

    strncpy(buf, input, sizeof(buf)+9); // non-null termination AND off-by-one! -- overwrite with 'A' on the last number of the canary, as it's zero (i.e. little endian 00 aa bb cc dd ee ff 11, so the 00 stops printing it out
                        // cause it's null, but if we use strncpy with an off-by-one that hits the last digit (first digit little endian) then we can print it out

    // also, 8 bytes is just empty part of the stack, so that's why it's 9 bytes. 8 empty bytes, + 1 off-by-one.

    print_str(buf);
}

int main()
{
    char input[1024];

    memset(input, 'A', sizeof(input));

    printf("Canary: %lx\n", get_canary());

    func(input);
}



Output:



$ gcc test.c

$ ./a.out
Canary: 6af07ba9ba12d800
41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141d812baa97bf06ad0ac548dff7f
4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 4141414141414141 6af07ba9ba12d841 7fff8d54acd0 55ce63ecb3f8 4141414141414141
Is this the canary getting leaked out? 6af07ba9ba12d841
Hint: Ignore the last two hex digits, as that's just 'A' character, overwriting the 0x00 null
*** stack smashing detected ***: terminated


Notice the bold/underline is the canary in reverse, because it's stored little endian on x86_64.

Video game, FPGA CPU or SDR?

...