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:
How can I see where the padding is and how do I know where to put the canary value?
Thank you.
CodePudding user response:
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)