Wednesday, October 11, 2006
strncpy fun
Lately I've been a tad busy doing some code projects. So I have neglected the blog a little bit. I have had some time lately to do some code audits and I've noticed some interesting types of bugs which some may misunderstand.

Commonly we think that strncpy will null terminate for us. Many of us already know this is not the truth. I recently saw some code which was doing something like the following:

char buf[BIG_BUFFER+1];
...
strncpy(buf, user_data, BIG_BUFFER);


So why is this bad? Well it might not be obvious if your not all that familiar with the operation of strncpy. The strncpy function copies data to another memory location. In this case we are copying user_data into buf. We also specify a size value of BIG_BUFFER which is how many bytes we need to copy. Many people have heard I'm sure that strncpy will null terminate for you. However, there is some truth to that but its not entirely all there is to it. It will null terminate if the data supplied to copy is less than the size passed to the function. We see here that BIG_BUFFER is less than BIG_BUFFER + 1. So what is the problem?

By setting user_data to a value >= to BIG_BUFFER we fill buf all the way to the last array slot. The last slot is left empty ... or is it?

In C strings are defined as a memory location which continues on until a null byte marks the end of it. 0x41 0x41 0x41 0x41 0x41 0x41 0x00 is an example of the string "aaaaaa". The null byte marks the end of the buffer.

The thing to remember in C is that memory starts out as uninitialized. So seemingly random data can be contained with memory which is not specifically assigned a value. In the above example we see the buf is never assigned a value. If it were this might not be a problem at all.

In our example we reach the next to last slot of the array buf. We leave the last array slot untouched. When the strncpy function finishes the array will not be null terminated as one might imagine due to the BIG_BUFFER+1 size declaration and the BIG_BUFFER strncpy argument. Instead that last slot of the array is uninitialized.

So if we look back to our definition of a string we can see that the expected null byte is not there so any functions which treat this memory as a string value will incorrectly read past the end of the buffer due to the uninitialized memory located at the last slot of the array.

Exploiting uninitialized memory bugs is a topic for another day. There are some great papers out there on the subject mercy@felinemenace has written one up a while back and Halvar has done some talks at Blackhat about it so if your interested search around and I'm sure you'll find what your looking for.
 
posted by bannedit at Wednesday, October 11, 2006 | Permalink | 0 comments