Buffer Overruns is one of top sources of security issues today. These are typically caused by trusting input data to a function that is external and is unchecked. Most of the times, this is unintentionally invoked by bad sloppy code. However, when done intentionally by a hacker, this can cause havoc. Some of the most common, buffer overrun prone functions include strcpy, memcpy, strcat etc… In unintentional buffer overruns, this mostly results in writing to memory not owned by your processes address space. In such cases this would end, in an access violation or a core dump, causing the program to be aborted in most cases. However, these buffer overruns can be exploited to run arbitrary code on the machine, even code that is injected in by the attacker.
There are different types of buffer overruns.
Static Buffer Overruns: These type of buffer overruns occur, when a buffer that is declared on the stack is overwritten by copying more data than the buffer can hold. It so happens, that the variables (buffer in this case) declared on the stack are located next to the return address of the function's caller. As I mentioned above, this usually occurs when user input is unchecked, e.g. strcat. And because the return address is next to the buffer on the stack, overwriting the buffer, means overwriting the return address, which is what gets executed with the function returns. An attacker can carefully exploit the overrun in such a way the data that is overwriting the return address, is an address of a function that he wants to execute.
Heap Overruns: Like Stack Overruns, Heap overruns can also cause memory and stack corruption. But unlike contrary developer belief, although heap overruns are harder to exploit, they are definitely exploitable.
Array Indexing Errors (Overruns and Underruns): These type of errors are less exploited compared to static buffer overruns. You can think of an array as a block on memory (buffer) that you can index into and then read/'write' from that location. Bad array implementation do not check indices well before access the memory locations. Sloppy code like this can be exploited to run arbitrary code and create havoc. (Well, in some cases you may never ever now that your machine is freely accessible and controlled by the attacker ). Again, unlike contrary developer belief, don't be fooled that only memory past the end of the array can be exploited.
Format Strings Exploits: These type of exploits are not exactly buffer overruns, but they lead to the same class of problems. These errors are usually caused in functions that take in variable number of arguments, because there isn't a good way for the function to determine the number of arguments passed into these functions. (printf family in the CRT). The %n type field for printf represents the number of characters successfully written so far to the stream or buffer. This value is stored in the integer whose address is given as the argument. So, this can basically be used to write into memory of the processes address space. But how can an attacker inject such code? The answer lies to the way the sloppy programmer writes code ala printf(input), rather than printf("%s", input). The latter prevent the user from using his own format, since its already defined, unlike the earlier case, where the input can be manipulated to create the format string.
In the next posts, I will go over examples of exploiting each of these examples and best practices to prevent such exploits from happening in the first place.