Search code examples
cbuffer-overflow

How to see the alignment of a struct in C?


I have an assignment where I need to log in to a simple program using a buffer overflow. The program takes two args with gets() and strcpy()'s them into v.username and v.password.

struct {
        int32_t goodcanary;
        char password[25];
        int32_t canary;
        char good_username[25];
        char good_password[25];
        char username[25];
    } v;

The canary is a 10 digit number which I know. Since a int32_t is only 4 bytes I converted the number to ascii and want to overflow password which is input2 and since canary comes after password in memory I thought I could put it at the end of input2 after it overflows. I can't get it working and I know that structs have padding but I don't know exactly how it works and where the padding is. Here is the memory locations of each member of the struct: screenshot

How can I see where the padding is and how do I know where to put the canary value?

Thank you.


Solution

  • The rules are basically as follows:

    • On systems with alignment requirements, a struct must always be allocated starting at an even address. For this reason, a struct needs to end with trailing padding bytes so that an array of such structs doesn't get the next array item misaligned.
    • On a computer with 4 byte alignment requirement for integers, each member in your struct that has such a requirement must start at an address evenly divisible by 4.
    • Character arrays have no alignment requirement so they may get allocated at any address.

    You can use offsetof (stddef.h) to print the byte position of any struct member. Example:

    #include <stdio.h>
    #include <stdint.h>
    #include <stddef.h>
    
    typedef struct 
    {
        int32_t goodcanary;
        char password[25];
        int32_t canary;
        char good_username[25];
        char good_password[25];
        char username[25];
    } v;
    
    #define print_offset(x) printf("Offset %s: %zu\n", #x, offsetof(v,x))
    
    int main (void)
    {
      printf("Size of struct: %zu\n", sizeof(v));
      print_offset(goodcanary);
      print_offset(password);
      print_offset(canary);
      print_offset(good_username);
      print_offset(good_password);
      print_offset(username);
      return 0;
    }
    

    Output (x86_64 computer):

    Size of struct: 112
    Offset goodcanary: 0
    Offset password: 4
    Offset canary: 32
    Offset good_username: 36
    Offset good_password: 61
    Offset username: 86
    

    Since canary starts at 32, there must have been 32-25-4=3 padding bytes inserted. And they must have been inserted after password since goodcanary is 4 byte aligned with no trailing padding necessary.

    Or if you will:

    offsetof(v, canary) - sizeof((v){0}.password) - offsetof(v,password)