2

I'm actually busy with learning more about buffer overflows. I read some interesting tutorials and just got the basic idea behind it. I tried to produce a vulnerable c++ file to test my knowledge against it, but it seems like I missed some of the concepts...

My code is the following:

   #include <iostream>
/* run this program using the console, or add your own getch, system("pause"), or input loop */

int main(int argc, char** argv) {


    char xx[20];
    char yy[20];
    std::cin >> xx;
    std::cout << xx << std::endl;
    std::cout << yy << std::endl;

}

In my opinion I should be able to write with a 21 Char-Long String in "xx" over the data in "yy". But "yy" is still full with some random chars ('cause no initialization) and not with the overflowing content of the variable "yy".

Could you tell me why this is happening?

Thanks in advance!

J. Doe
  • 123
  • 2
  • 2
    You're assuming that yy comes after xx in memory, perhaps yy comes before xx. Have you checked that? – Swashbuckler Jun 14 '19 at 16:25
  • 2
    Do you know how to use a debugger to step through execution and actually see where in memory these arrays are pointed at? – DarkMatter Jun 14 '19 at 16:48
  • Try redoing as a function call. The values will then be added to the function stack in sequence. See https://zhu45.org/posts/2017/Jul/30/understanding-how-function-call-works/. – Stone True Jun 15 '19 at 02:03

3 Answers3

3

You have to check the addresses of the char arrays, because your assumption that yy starts right after xx in memory is not necessarily true. I modified your code a bit so that it prints the addresses:

#include <iostream>

int main() {

    char xx[20];
    char yy[20];


    std::cin >> yy;

    std::cout << "xx: " << xx << std::endl;
    std::cout << "yy: " << yy << std::endl;
    std::cout <<std::endl;
    std::cout <<std::endl;
    std::cout << "Addresses: " <<std::endl;
    std::cout << "Address of xx: " << &xx << std::endl;
    std::cout << "Address of yy: " << &yy << std::endl;

    return 0;

}

In the output you can see that in my case yy actually came before xx in memory. The addresses show that they are 32 bytes apart. So by typing 33 chars into yy I was able to overwrite the first byte of xx. As you can see in this output below:

012345678901234567890123456789012
xx: 2
yy: 012345678901234567890123456789012


Addresses: 
Address of xx: 0x7fff31b68b50
Address of yy: 0x7fff31b68b30

Please also note that this may be completely different on your machine.

Lord Vapor
  • 76
  • 1
  • 1
  • 8
1

Could you tell me why this is happening?

When Visual Studio compiles this code on my machine, it puts the buffer "xx" at the memory location 0x012ff894. It puts "yy" at memory location 0x012ff878.

So, yy is at a lower address than xx.

Therefore you can not overflow xx into yy by writing more data into xx since that writing goes to 0x012ff894, 0x012ff895, 0x012ff896, etc. That is, your input only gets written to the address of xx and higher addresses, but yy is at a lower address.

On the other hand, if I wanted to overflow the buffer xx into the buffer argv, I could do that because the compiler puts argv at a higher address than xx.

hft
  • 4,910
  • 17
  • 32
0

The compiler could put your two variables right next to each other on the stack, but it is in no way forced to. It could choose to put them at aligned locations, it could choose to swap their order.

Ultimately to understand the behaviour of a buffer overflow you have to look at the assembler, the same C++ source built under different circumstances (compiler versions, target platforms, optimisation levels etc) may lead to different results.

Peter Green
  • 4,918
  • 1
  • 21
  • 26