Other Overflows

This section is dedicated to those overflows that are neither stack- nor heap-based.

.data section overflows

A program is divided into different areas called sections . The actual code of the program is stored in the .text section; the .data section of a program contains such things as global variables . You can dump information about the sections into an image file with dumpbin using the /HEADERS option and use the /SECTIONS:.section_name for further information about a specific section. While considerably less common than their stack or heap counterparts, .data section overflows do exist on Windows systems and are just as exploitable, although timing can be an obstacle here. To further explain, consider the following C source code:

 #include <stdio.h> #include <windows.h>     unsigned char buffer[32]=""; FARPROC mprintf = 0; FARPROC mstrcpy = 0;     int main(int argc, char *argv[]) {          HMODULE l = 0;      l = LoadLibrary("msvcrt.dll");      if(!l)             return 0;      mprintf = GetProcAddress(l,"printf");      if(!mprintf)             return 0;      mstrcpy = GetProcAddress(l,"strcpy");      if(!mstrcpy)             return 0;      (mstrcpy)(buffer,argv[1]);      __asm{ add esp,8 }      (mprintf)("%s",buffer);      __asm{ add esp,8 }      FreeLibrary(l);          return 0; } 

This program, when compiled and run, will dynamically load the C runtime library ( msvcrt.dll ), and then get the addresses of the strcpy() and printf() functions. The variables that store these addresses are declared globally, so they are stored in the .data section. Also notice the globally defined 32-byte buffer. These function pointers are used to copy data to the buffer and print the contents of the buffer to the console. However, note the ordering of the global variables. The buffer is first; then come the two function pointers. They will be laid out in the .data section in the same way ”with the two function pointers after the buffer. If this buffer is overflowed, then the function pointers will be overwritten, and when referenced ”that is, called ”an attacker can redirect the flow of execution.

Here's what happens when this program is run with an overly long argument. The first argument passed to the program is copied to the buffer using the strcpy function pointer. The buffer is then overflowed overwriting the function pointers. What would be the printf function pointer is called next , and the attacker can gain control. Of course, this is a highly simplistic C program designed to demonstrate the problem. In the real world, things won't be so easy. In a real program, an overflowed function pointer may not be called until many lines later ”by which time the user -supplied code in the buffer may have been erased by buffer reuse. This is why we mention timing as a possible obstacle to exploitation. In this program, when the printf function pointer is called, EAX points to the beginning of the buffer, so we could simply overwrite the function pointer with an address that does a jmp eax or call eax . Further, since the buffer is passed as a parameter to the printf function, we can also find a reference to it at ESP + 8 . This means that, alternatively, we could overwrite the printf function pointer with an address that starts a block of code that executes pop reg , pop reg , ret . In this way, the two pops will leave ESP pointing to our buffer. So, when the RET executes, we land at the beginning of our buffer and start executing from there. Remember, though, that this is not typical of a real-world situation. The beauty of .data section overflows is that the buffer can always be found at a fixed location ”it's in the .data section ”so we can always overwrite the function pointer with its fixed location.

TEB/PEB Overflows

For the sake of completeness, and although there aren't any public records of these types of overflows, the possibility of a Thread Environment Block (TEB) overflow does exist. Each TEB has a buffer that can be used for converting ANSI strings to Unicode strings. Functions such as SetComputerNameA and GetModuleHandleA use this buffer, which is a set size . Assuming that a function used this buffer and no length checking was performed, or that the function could be tricked with regards to the actual length of the ANSI string, then it could be possible to overflow this buffer. If such a situation were to arise, how could you go about using this method to execute arbitrary code? Well, this depends on which TEB is being overflowed. If it is the TEB of the first thread, then we would overflow into the PEB. Remember, we mentioned earlier that there are several pointers in the PEB that are referenced when a process is shutting down. We can overwrite any of these pointers and gain control of execution. If it is the TEB of another thread, then we would overflow into another TEB.

There are several interesting pointers in each TEB that could be overwritten, such as the pointer to the first frame-based EXCEPTION_REGISTRATION structure. We'd then need to somehow cause an exception in the thread that owns the TEB we've just conquered. We could of course overflow through several TEBs and eventually get into the PEB and hit those pointers again. If such an overflow were to exist, it would be exploitable, made slightly difficult, but not impossible , by the fact that the overflow would be Unicode in nature.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net