Search code examples
csecurity

Security threats when using bar() vs bar(void)


For HW in a security class, I want to demonstrate an attack that relies on the difference between bar() (tells the compiler that the number and type of arguments is unknown) and bar(void) (tells the compiler that the function doesn't take arguments).

I've seen this thread that details their difference, but haven't been able to create a successful attack based off of it.

My code is:

#include <stdio.h>

void bar(){
    int a = 4;
    printf("%d", a);
}


int main() {
    bar("hhhhhhhhhhhhhhhhhhhhhhhh");

    return 0;
}

I'm expecting for the passed string to overrun the variable 'a', but it doesn't happen. Starngely enough, when examining the stack with gdb (using 'info frame'), it doesn't say that the string has been even passed.


Solution

  • Starngely enough, when examining the stack with gdb (using 'info frame'), it doesn't say that the string has been even passed.

    The strings are not passed in the C language by value only by pointer. So you pass the reference to the string literal "hhhhhhhhhhhhhhhhhhhhhhhh" String literal will be stored where implementation stores constant data (not on the stack)

    If you want to pass by value large array you need to use structures which are passed by value.

    bar((struct {char a[30];}){"hhhhhhhhhhhhhhhhhhhhhhhh"});
    

    It will be placed on the stack (with optimizations disabled)

    main:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 32
            movabs  rax, 7523377975159973992
            mov     rdx, rax
            mov     QWORD PTR [rbp-32], rax
            mov     QWORD PTR [rbp-24], rdx
            movabs  rax, 7523377975159973992
            mov     edx, 26728
            mov     QWORD PTR [rbp-18], rax
            mov     QWORD PTR [rbp-10], rdx
            sub     rsp, 32
            mov     rcx, rsp
            mov     rax, QWORD PTR [rbp-32]
            mov     rdx, QWORD PTR [rbp-24]
            mov     QWORD PTR [rcx], rax
            mov     QWORD PTR [rcx+8], rdx
            mov     rax, QWORD PTR [rbp-18]
            mov     rdx, QWORD PTR [rbp-10]
            mov     QWORD PTR [rcx+14], rax
            mov     QWORD PTR [rcx+22], rdx
            mov     eax, 0
            call    bar
            add     rsp, 32
            mov     eax, 0
            leave
            ret
    

    But the called function will create its own stack frame - separate from the main function one

    bar:
            push    rbp
            mov     rbp, rsp
            sub     rsp, 16
            mov     DWORD PTR [rbp-4], 4
            mov     eax, DWORD PTR [rbp-4]
            mov     esi, eax
            mov     edi, OFFSET FLAT:.LC0
            mov     eax, 0
            call    printf
            nop
            leave
            ret
    

    So nothing dangerous will happen as both stack frames do not overlap.