I am working on a security engineering assignment where I need to create a buffer overflow exploit to change the execution flow of a C program. The goal is to overwrite the return address and redirect execution to a specific function (dump_users). However, I keep encountering a segmentation fault, and I need help to resolve this.
Program Details
Here’s the relevant part of my C program:
#include <stdio.h>#include <stdlib.h>#include <string.h>#define USERNAME_SIZE 32#define PASSWORD_SIZE 16#define FILENAME "users.txt"typedef struct { char username[USERNAME_SIZE]; char password[PASSWORD_SIZE];} User;void register_user() { FILE *file = fopen(FILENAME, "a"); if (file == NULL) { perror("Error opening file"); return; } User user; printf("Enter username: "); gets(user.username); // Vulnerable function printf("Enter password: "); gets(user.password); // Vulnerable function fwrite(&user, sizeof(User), 1, file); fclose(file); printf("User registered successfully.\n");}void login() { FILE *file = fopen(FILENAME, "r"); if (file == NULL) { perror("Error opening file"); return; } char username[USERNAME_SIZE]; char password[PASSWORD_SIZE]; User user; int authenticated = 0; printf("Enter username: "); gets(username); printf("Enter password: "); gets(password); while (fread(&user, sizeof(User), 1, file)) { if (strcmp(username, user.username) == 0 && strcmp(password, user.password) == 0) { authenticated = 1; break; } } fclose(file); if (authenticated) { printf("Login successful!\n"); } else { printf("Login failed!\n"); }}void dump_users() { FILE *file = fopen(FILENAME, "r"); if (file == NULL) { perror("Error opening file"); return; } User user; printf("Registered users:\n"); while (fread(&user, sizeof(User), 1, file)) { printf("Username: %s, Password: %s\n", user.username, user.password); } fclose(file);}int main() { int choice; while (1) { printf("1. Register\n"); printf("2. Login\n"); printf("3. Dump users\n"); printf("4. Exit\n"); printf("Enter your choice: "); scanf("%d", &choice); switch (choice) { case 1: register_user(); break; case 2: login(); break; case 3: dump_users(); break; case 4: return 0; default: printf("Invalid choice.\n"); } } return 0;}
I want to perform a buffer overflow attack by overwriting the return address to call the dump_users function when register_user returns.
Details from GDBAddress of dump_users: 0x555555555718Buffer overflow point: gets(user.username)Buffer size: 32 bytesSaved return address offset: 40 bytes from the start of the buffer (considering padding and saved rbp).
Compiled the program without stack protection and with ASLR disabled:
gcc -fno-stack-protector -o main main.csudo sh -c 'echo 0 > /proc/sys/kernel/randomize_va_space'Created the payload:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x18\x57\x55\x55\x55\x55\x00\x00Input the payload manually during the register_user prompt:Enter username: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x18\x57\x55\x55\x55\x55\x00\x00
ProblemDespite following these steps, I still encounter a segmentation fault after the payload is executed. Here’s the GDB output:
Program received signal SIGSEGV, Segmentation fault.0x00005555555553ba in register_user () at main.c:3939 }
GDB Frame Information
(gdb) info frameStack level 0, frame at 0x7fffffffdad0: rip = 0x55555555534c in register_user (main.c:32); saved rip = 0x55555555570f called by frame at 0x7fffffffdb00 source language c. Arglist at 0x7fffffffdac0, args: Locals at 0x7fffffffdac0, Previous frame's sp is 0x7fffffffdad0 Saved registers: rbp at 0x7fffffffdac0, rip at 0x7fffffffdac8(gdb) x/20x $rsp0x7fffffffdaa0: 0x00000000 0x00000000 0xffffdaf0 0x00007fff0x7fffffffdab0: 0x00000000 0x00000000 0xffffdaf0 0x00007fff0x7fffffffdac0: 0xffffdaf0 0x00007fff 0x5555570f 0x000055550x7fffffffdad0: 0xffffdc08 0x00007fff 0x00000000 0x000000010x7fffffffdae0: 0x00000000 0x00000000 0x00000000 0x00000001
QuestionHow can I correctly craft the payload to overwrite the return address and redirect execution to the dump_users function? What am I missing in my current approach?