2

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?

Andre Helberg
  • 552
  • 1
  • 6
  • 17
  • I would never have expected any similarity of behavior between Windows and Linux machines. Differences between Linux systems can be explained by architectural differences (memory mapping) or versioning of the elements that made up the program or OS version... –  Nov 28 '15 at 12:47

2 Answers2

1

Undefined behavior is, as you have discovered, undefined. Trying to explain it is in general not terribly productive.

In this case it's almost certainly due to the arrangement of your stack and padding bytes inserted by/between the local variables varying between compiler/system.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • Sorry but this should not be "undefined behaviour", the compiler is a program and should thus follow a defined set of steps when compiling the program. If what OP says is true, two linux machines both probably running gcc should conceivably deliver the same executable with the same results – Andre Helberg Aug 14 '14 at 21:05
  • @Chaosekie The language explicitly gives compilers leeway to do different things on different machines, let alone different compilations on the same machine. – Mark B Aug 14 '14 at 21:10
  • could you please give a reference to where this is defined? And it seems the OP got consistently the same results on the 3 different machines ( he took the time too count the number of chars it takes to overflow ) – Andre Helberg Aug 14 '14 at 21:12
1

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.

Community
  • 1
  • 1
lapk
  • 3,838
  • 1
  • 23
  • 28
  • Thanks, this is exactly what I was looking for. Cause I thought the char array would receive 5bytes and the int would have 4 bytes after that. Then when the overflow happens it would go into the int's space. I also read that the allocation works in words where the char array would then be 8bytes as you are stating. – Jaco van Rensburg Sep 16 '13 at 22:23
  • @user2715411 Well, you are absolutely correct that overflow occurs when your "input" buffer is larger than the stack variable (array) it is copied into. It's just that there are internal things to consider, such as stack alignment, padding, variables placement - all of which will manifest itself in slightly different behavior (different length to overflow or stack corruption). Other than that - it's what you described. – lapk Sep 16 '13 at 22:31