The buffer overflow vulnerability appears where an application needs to read external information such as a character string, the receiving buffer is relatively small compared to the possible size of the input string, and the application doesn't check the size. The buffer allocated at run-time is placed on a stack, which keeps the information for executing functions; such as local variables, argument variables, and the return address. The overflowing string can alter such information. This also means that an attacker can change the information as he wants to. For example, he can inject a series of machine language commands as a string that also leads to the execution of the attack code by changing the return address to the address of the attack code. The ultimate goal is usually to get control of a privileged shell by such methods.
Figure 1 shows a typical stack structure after a function is called. The stack pointer points at the top of stack, which is at the bottom in the figure. The programming language C uses the area from the top of the stack in the following order: local variables, the previous frame pointer, the return address, and arguments of the function. This data is called the frame of the function, which represents the status of the function. The frame pointer locates the current frame and the previous frame pointer stores the frame pointer of the caller function.
The function foo (see Figure 2) is a vulnerable function, which produces the stack structure such as shown in Figure 1. It reads the content of the environment variable ``HOME'' into the ``buffer'' which has a size of 128 bytes. Since the function strcpy doesn't check the size of the output, it can copy more than 128 bytes of data to the ``buffer''. Imagine the ``HOME'' variable has this string: 128 bytes of 41, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, and 3. This will assign 128 character 'A's, 0x01010101, 0x02020202, and 0x03030303 into the ``buffer'', ``lvar'', the previous frame pointer, and the return address respectively. (We assume that 32-bit variables are used by default and that C language notation is used.) When the function foo finishes it's operations and returns to the caller based on this memory arrangement, it will go back to the address 0x03030303, which isn't the caller address. If malicious code is located at the address, it is executed with the same privilege level as the application.
We will now introduce a classification of attack methods, how an attacker acquires control of the application. In the first category the target of the attack is to show in the stack. The following lists the data stored in this area and describes the attack method used.
It is the most popular point of attack by changing the value of the return address to the address of malicious code.
The function pointer variable is a another target for acquiring the control. Assigning the function pointer variable of an argument or a local variable to the attack code is a typical attack method. In this case, the vulnerable place can be found by checking the source program.
There is a third attack method using redirection. Assume that a variable is declared as the pointer of the structure that holds a function pointer. This is vulnerable to attack, but it is hard to find it without traversing the pointer. However , an attacker can create a fake structure that has the same contents as the original except for the function pointer.
There is a possibility that changing a pointer variable which is not a function pointer variable will acquire the control of the application. In the case of the function foo from Figure 2, the pointer variable ``lvar'' can be changed to point to the location of the return address. If there is a statement that modifies the value pointed to by ``lvar'' after the ``strcpy'' statement, changing the return address may be possible.
Attacking the previous frame pointer can also take the control of the application. The connection between the previous frame pointer and the return address is based on the following dependencies: