Hade Bayaa
Hade Bayaa

Reputation: 31

Buffer Overflow Exploit to Redirect Execution to Another Function Causes Segmentation Fault

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 GDB Address of dump_users: 0x555555555718 Buffer overflow point: gets(user.username) Buffer size: 32 bytes Saved 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.c
sudo sh -c 'echo 0 > /proc/sys/kernel/randomize_va_space'

Created the payload:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x18\x57\x55\x55\x55\x55\x00\x00
Input the payload manually during the register_user prompt:

Enter username: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x18\x57\x55\x55\x55\x55\x00\x00

Problem Despite 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:39
39      } 

GDB Frame Information

(gdb) info frame
Stack 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 $rsp
0x7fffffffdaa0: 0x00000000      0x00000000      0xffffdaf0      0x00007fff
0x7fffffffdab0: 0x00000000      0x00000000      0xffffdaf0      0x00007fff
0x7fffffffdac0: 0xffffdaf0      0x00007fff      0x5555570f      0x00005555
0x7fffffffdad0: 0xffffdc08      0x00007fff      0x00000000      0x00000001
0x7fffffffdae0: 0x00000000      0x00000000      0x00000000      0x00000001

Question How 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?

Upvotes: 3

Views: 84

Answers (0)

Related Questions