Home > Articles > Security > Buffer Overflow Protection by Yash K.S

Buffer Overflow Protection by Yash K.S

Posted: March 20th, 2007 @ 5:55am

After several years of innovation in protecting against the Buffer overflow, still there is no one solution to help to guard against Buffer overflow. We need to combine more then one method to mitigate the issue. All the current innovation is still in preliminary stage and yet to take some shape in Future.
To prevent buffer overflow steps has to be taken in several levels and few of levels could be:
Hardware should provide better support
Built-in OS support
C runtime libraries should be safe in processing any type of buffer
Compiler support
Programmer should be aware of security risks
In recent years, there are some innovations to prevent stack based attacks in both hardware and software, but most programmers still not aware of security risks during development of products.
Hardware based protection (DEP)
Intel and AMC has implemented feature which disables execution in Stack and Data segments. Intel markets this feature as XD (eXecute Disable) and AMD markets as NX (No eXecute), both has same functionality, only name is changed. AMD64 and Intel’s P4 codenamed Prescott (EMT64) supports this feature.
Identifying CPU supports this protection can be done using CPUID instruction. This protection is implemented using the existing reserve field of Page Table Entry (PTE), PTE is size of 64 bites and XD uses the last bit i.e., 63rd bit. If PAE (Physical address extension) is enabled then 63 bit is used as XD bit or else it will treat 63rd bit as reserved. If this bit is enabled for any page, then CPU cannot execute any code from that page.
It NX bit is enabled and if application is trying to execute code in stack or data segment where this bit is enabled, CPU will throw exception and leave to OS to handle it further.
Operating System based protection
XP SP2 DEP based protection: This is OS implementation to prevent any execution of code in memory pages, heap, stack and other data sections. OS will prevent all kinds of attack which is based on Exception handling mechanism in windows. This will be supported in all machines if it runs XP and SP2. By default software based DEP will only protect limited system binaries.
C Runtime libraries
Generally, most of the C function which is provided to process buffer is vulnerable to attack. Many of these functions do not take into account secure coding guidelines. There is no internal checking’s for buffer overflow and all these function blindly does what you ask for without checking underflow or overflow.
Some of the C functions which is vulnerable are strcpy(), strcat(), sprintf() etc… and similarly you can find huge list, almost all of string functions in C/C++ library. Even the integer manipulation has the same problem. Unless programmer manually handles and there is no built-in way.
Visual studio 2005 removes most of these functions and make sure programmer passed the size of the buffer and even other compilers has implemented library which is safer. For ex: instead of strcpy(), it enforces to use strncpy().
Visual C/C++ /GS option
/GS compiler switch is a cookie which is placed in between the buffer and return address. After placing the cookie the stack looks like following:
Cookie value: Cookie is a random value which is generated using the combination of the time, process id, thread id, tick count and performance counter. All these fields are XOR’d and used as cookie value and this is only 4 bytes value. This cookie should not be Zero and due the nature of generation it will be a random in different application. This generation happens when application begins and using C function __security_init_cookie().
After generating this 4 byte cookie value, it will assign to global cookie variable. In each function it will insert this value between the Buffer and return address. After executing the function it will check the local stored cookie value with global cookie value, if its not matching that means some corruption happened and it will halt the application by displaying following error message box:

C Example of Buffer overflows:

Code generated by compiler for this sample is as follow:

Take a look at following disassembled code. Before execting the strcpy() function, stack was proper ( read Marked rectangle ) :

0x0012F9F8 is a ESP value and pointing to top of the stack. Stack value is as follow:
0x00401e1d : Return address
0x0012fa18 : EBP register value
0xb2703066 : Cookie value
0x008f07c4 & 0x00000212 : are allocated to Buffer variable with extra alignment bytes. This value is a junk value since in our sample we just declared without assigning any value to it.
0x00403c20 : This is a address for a string “This is Testing” and this is stored in read only data segment.
0x0012fa00 is a address of a Buffer variable which is passed to strcpy() function.
After executing the instruction “CALL 004025F8” ( strcpy() function ), stack will look like following:

If you carefully observe above figure and previous, you can easily identify the cookie value 0xb2703066 is overwritten. After calling the function to compare global and local cookie, if there is any change it will call Buffer overflow message box.
Visual C/C++ RunTime Checks (/RTC)
Runtime checking switched is a good addition to a latest version of VC++. This option works only for in non-optimized binary. But it works both on Debug and Release binaries (Although there is less chance that anyone is going to compiler the release binary without optimization). There are 3 switches /RTCs , /RTCu & /RTCc
Runtime check following error conditions:
It helps in stack pointer verification around every function call. This helps mainly in preventing the calling convention problem and it also helps checking overflow and underflow of all variables. This is done by adding 0xCCCCCCCC ( 4 bytes ) before and after the variable.

Error box clearly mentions which Buffer is corrupted.

We are trying to copy pSrcPtr (un-initialized pointer) to Buffer variable. After executing the strcpy() function at the end of the function it throws above error.

We are trying to assign 0x800000 integer value to char type ‘c’. Once it reaches end of the function it will display above error box.
Let’s dig deep into how does /RTCs are really implemented by taking following code as sample:

Once it enters the function, it will make all the variables 0xCC including alignment space. Each and every variable is places between 0xCC ( INT 3) byte. To achive this functionality take a look at following disassembled code of RTCFunc() what kind of code compiler is going to add it:

If you have a variable and its value is 0x12345678. This is guarded in stack like:
0xCCCCCCCCCCCCCCCC (8bytes)
0x12345678(4bytes)
0xCCCCCCCCCCCCCCCC(8bytes)
After executing the function if any of the 0xCC byte is overwritten, then it is will identify which variable is corrupted and reports in error dialog Box. Take a look at following figure and when code is proper without overflow or underflow:

Blocked rectangle is a stack data. After executing the function to copy strings to all 3 buffers, you can see the data in stack in following order:
0x004155C8 : Return address
0x0012f308 : EBP register data
0xCCCCCCCC : Bytes which is overwritten by compiler inserted code
0x00434241 : BufferOver data of “ABC”
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
0x00454443 : BufferOver1 data of “CDE”
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
0x00484746 : BufferOver2 data of “FGH”
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
Take a look at following code if there is any overflow or underflow how it overwrites. In this example I am going to 7 bytes of data to BufferOver variable:

Stack representation of overwritten data of above figure is as follow:
0x004155C8 : Return address
0x0012f308 : EBP register data
0x004e4d4c is Over written data instead of 0xCCCCCCCC. By checking this value with 0xCC compiler will identify which variable has courrupted
0x00434241 : BufferOver data of “ABCKLMN” ( This variable is using the next bytes which is not reserved for this purpose.
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
0x00454443 : BufferOver1 data of “CDE”
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
0x00484746 : BufferOver2 data of “FGH”
0xCCCCCCCCCCCCCCCC: Bytes which is overwritten by compiler inserted code
Following is the disassembled code for checking the variables for consistency of 0xCC bytes. Compiler has its own function of _RTC_CheckStackVars() function :

Although, if you use all of these protection methods, it will only mitigate the risk of buffer overflow in certain conditions. But these are not fool proof methods. You might even need to use 3rd party Protection software’s. Most of these problems can be mitigated if the developer has the awareness about security risks during the development of the product.