c++buffer-overflow

C++ buffer overflow different on 3 machines


I am testing a simple buffer overflow in c++. The example is a test where given that checks are not in place, a malicious user could overwrite variables using a buffer overflow.

The example defines a buffer and then a variable, this means that space should be allocated for the buffer, and then space for the variable. The example reads from cin to a buffer of length 5, and then checks if the admin variable is set to something other that 0, if it is, the user conceptually gained admin access.

#include <iostream>
using namespace std;

int main()
{
    char buffer[5];
    int admin = 0;

    cin>>buffer;
    if(strcmp(buffer,"in") == 0)
    {
        admin = 1;
        cout<<"Correct"<<endl;
    }
    if(admin != 0)
        cout << "Access" << endl;
    return 0;
}

I have 3 machines, 1 Windows and 2 Linux systems.

When I test this on windows (CodeBlocks) it works (logically) entering more than 5 characters overflows and rewrites the the admin variable's bytes

Now my first linux system also works but only when I enter 13 characters, is this to do with different compilers and how they allocate memory to the program?

My second linux machine can't overflow at all. It will give a dump error only after the 13th character.

Why do they differ that much?


Solution

  • You should examine disassembly. From there you will see what happens precisely.

    Generally speaking, there are two things to consider:

    1. Padding done by the compiler to align stack variables.

    2. Relative placement of the stack variables by the compiler.

    The first point: Your array char buffer[5]; will be padded so int admin; will be properly aligned on stack. I would expect it to be generally padded to 8 bytes on both x86 or x64 and so 9 symbols to overwrite. But compiler might do differently depending on what it sees fit. Nonetheless, it appears that Windows and Linux machines are x86 (32bit).

    The second point: compiler is not required to put stack variables on stack in order of their declaration. On Windows and first Linux machine compiler does indeed place char buffer[5]; below int admin;, so you can overflow into it. On second Linux machine, compiler chooses to place it in reverse order, so instead of overflowing into int admin;, you are corrupting stack frame of the caller of main() after writing beyond space allocated for char buffer[5];.

    Here is shameless link to my own answer to a similar question - an example of examining of such overflow.