2

I am trying to demonstrate a buffer overflow via an array index (when there isn't any bounds checking). What I am trying to do is change my bool authenticated = false to true by passing in a bad value.
I am using GCC 4.8.5

arrayVulnerability(int size)
{
   int array[4];
   bool authenticated = false;

   for (int i = 0; i < size; i++)
   {
      array[i] = size;
   }
}

My understanding is that my memory is set up as follows: enter image description here

I was hoping that by passing an int larger than 4 I would be able to overwrite that position to true but it's not working. I'm curious if I have my memory misunderstood or if I am missing something?

Edit: I printed out the locations as suggested and got the following:

bool authenticated = 0x7ffc4741612f
array[0] = 0x7ffc47416130
array[1] = 0x7ffc47416134
array[2] = 0x7ffc47416138
array[3] = 0x7ffc4741613c
array[4] = 0x7ffc47416140

So it looks like bool authenticated is before my array and my memory layout was wrong. I'm still confused about why it is before my array however.

Kirby
  • 77
  • 9
  • 1
    retry with order of `array` and `authenticated ` reverted. – Jarod42 Nov 09 '18 at 21:09
  • @Jarod42 I switched those around and tried it that way but got the same result. Is the way I'm conceptualizing the memory incorrect? – Kirby Nov 09 '18 at 21:15
  • 3
    What you're trying to do is considered Undefined Behavior, which means you cannot guarantee the behavior you want on every platform and compiler. If, however, you specify exactly which compiler you're using, and the target environment you're compiling for, we might be able to answer this question more directly. – Xirema Nov 09 '18 at 21:19
  • 1
    If this is the real code posted, the whole function is most likely to be optimized away altogether. If this is not, please post one - including target system, compiler and compiler switches. When dealing with undefined behavior, every little bit matters. – SergeyA Nov 09 '18 at 21:20
  • Why do you think that `array` and `authenticated` are next to each other in the memory? – ducminh Nov 09 '18 at 21:20
  • 3
    Did you try checking the actual addresses of these variables while debugging the program? – r3mus n0x Nov 09 '18 at 21:24
  • @Xirema I am compiling with GCC 4.8.5 – Kirby Nov 09 '18 at 21:27
  • 1
    Look at [that](http://coliru.stacked-crooked.com/a/40359b186fc683c1). – Jarod42 Nov 09 '18 at 21:30
  • why loop && why do you write `size` to the storage array slots - why not write -1 to `array[4]` directly – pm100 Nov 09 '18 at 21:31
  • 1
    add a line that does `printf("%p %p\n", &array[4], &authenticated)` to see if memory is laid out as you expected – pm100 Nov 09 '18 at 21:32
  • I printed out the memory like most of you suggested and you are right it's not in the layout I assumed. I'm just unsure as to why. – Kirby Nov 09 '18 at 21:40
  • 1
    Also **note** *one-past-the-end-of-an-array* is a **valid address** you can reference (but not alter). – David C. Rankin Nov 09 '18 at 21:47

1 Answers1

2

The most likely implementation of automatic storage, the stack, grows downwards as objects are allocated. This means that array is allocated a certain address, and then authenticated is allocated a lower address. You can do some quick experiments to verify if this is the case. Either look at the state of an object defined before array, or print the addresses of the objects.

Tim Randall
  • 4,040
  • 1
  • 17
  • 39
  • I printed out the locations like you suggested, and you were right. It looks like the item I'm looking for is before the array. I'm not sure why that is however. – Kirby Nov 09 '18 at 21:39
  • 2
    @Kirby: Sometimes it isn't. That's the kind of wackiness you can expect when you rely on behavior outside of what C++ guarantees. Hell, in some cases, you might overwrite some temporary variable the compiler decided to stick in between the two. – cHao Nov 09 '18 at 21:52
  • @cHao so I'm guessing what I'll need to do is manually find the address of items I want to alter every time and go from there? – Kirby Nov 09 '18 at 21:54
  • 1
    @Kirby: Not necessarily every time...but if you are intentionally overrunning your buffer, you would do well to know how your compiler is arranging things. Which implies you should check the relevant addresses once at least. The resulting code might not work anywhere else, but it might still help you. :) – cHao Nov 09 '18 at 21:59
  • 1
    Even better -- the arrangement of the stack can change based on compiler options and optimizations. – David C. Rankin Nov 09 '18 at 22:06
  • 1
    @Kirby you may also want to visit the gcc specific page [GNU libc - 3.2.1 Memory Allocation in C Programs](https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-and-C.html#Memory-Allocation-and-C) and note *"In GNU C, the size of the automatic storage can be an expression that varies. In other C implementations, it must be a constant."* – David C. Rankin Nov 09 '18 at 22:13
  • @DavidC.Rankin I'll head there now and take a look. Thank you! – Kirby Nov 09 '18 at 22:15