Fog Creek Software
Discussion Board

How is a buffer overrun a virus threat?

Last year in July news was that ShellExecute made Windows 2000 vulnerable because of the buffer overflow when you typed more than 4000 characters in the third argument (for the path of the file to be opened/explored/printed). There was no boundary checking and as a result, it caused a buffer overrun. OK, undertood. It could cause the program that used ShellExecute to crash until SP4 came out.

My question is, how does a buffer overrun pose a potential virus threat to applications and how could this buffer overrun have been exploited by malicious code writers?

Sathyaish Chakravarthy
Tuesday, March 30, 2004

i like i
Tuesday, March 30, 2004

By passing a very long string in a fixed size buffer, that string overflows the buffer. It overwrites part of the stack.

The stack contains the return address of the procedure (the one stored on the stack by the CALL instruction).

So, if you overwrite the return address, when the procedure returns, you can make the CPU execute instructions from the address you tell it to.

So, the trick is to pass a string in such a way that:

- the string contains a small machine-code program which does what you want (for example, download an .EXE using WinInet functions and run it)

- the return value is overwritten in such a way that it passes control to the small program

When the procedure returns, your small machine-code program will get executed, and will be able to download the .EXE, for example, or to offer a remote shell to an attacker, etc.

After this code finishes execution, the "host" program (the one that contains a buffer overflow) usually terminates (is terminated by the exploit code) or crashes.

Buffer overflow exploits usually work only for a certain version of the host program, because they are dependent on the "host" code being at a certain address in memory.

Buffer overflow bugs are specific to C and C++ programs which use fixed length arrays to store strings.

Tuesday, March 30, 2004

Thank you so much, MX, for that little tutorial. I enjoyed reading it.

Sathyaish Chakravarthy
Tuesday, March 30, 2004
Tuesday, March 30, 2004

There is a book "Writing Secure Code" from Howard &
LeBlanc. In there you can find a good example how to do it.

There are few other nice topics in this book, but I found
most useful things about how to avoid Admin-user

Tuesday, March 30, 2004

Why don't programs control the amount of data that is read into a buffer?  Using the example given above,  why isn't the program written so:

    read data into buffer
    only read a maximun of 4000 bytes and then stop

This seems like basic common sense.
What am I missing?

My Cousin Vinniwashtharam
Tuesday, March 30, 2004

Because common sense is the least used sense of all. :))

Because programmers use strcpy instead of strncpy...

Tuesday, March 30, 2004

If I'm interpreting the article correctly, apparently some people are writing code like this:

void foo(const char* s)
  char buffer[SOME_FIXED_LENGTH];

... whereas instead they should write code more like this:

void safestrncpy(char* to,const char* from,size_t n)
  if (!n) return;
  //copy the string, but not too much of it
  //strncpy may not ensure that the copied string is null-terminated
  to[n-1] = '\0';

void foo(const char* s)
  char buffer[SOME_FIXED_LENGTH];

Christopher Wells
Tuesday, March 30, 2004

>Why .... read data into buffer .... only read a maximun of 4000 bytes and then stop

Some unintentional overflows may have been caused, I can only guess, because of the lengthy QueryString URLS in browsers. Others, as in most of them, should be the result of malicious code.

Sathyaish Chakravarthy
Tuesday, March 30, 2004

I've seen it mentioned that if systems would only stop growing stacks down in memory, it would be a lot harder to exploit buffer overflow.  Since you are usually working on the top frame of the stack, a buffer overflow would only write off of the top of the stack, not write deeper down into the stack, and probably not over any stack frames and return addresses.

Keith Wright
Tuesday, March 30, 2004

I had the same thought -- if only the stack grew upwards instead of downwards, there would be much less opportunity to overwrite the return address.

What is the rationale anyway to *decrease* the stack pointer on pushes? The stack is *growing* when you push things onto it.

It must be some historical reason?
Tuesday, March 30, 2004

Having stack to grow the other direction will not help to this particular set of exploits as long as any address that causes execution to branch is available somewhere in the data. I.e. VMT, function pointers are the same things as return address from this point of view.

Wednesday, March 31, 2004

"Because programmers use strcpy instead of strncpy..."

No, because the C language is 30 years old and those (four) dumb asses at the ISO refused, even after all the buffer overflow chaos of the past decade, to standardize safe, usable string functions.

strncpy() and strncat() are meant for copying/concatenating x characters from one string to another, not copying/concatenating one string to another of x size.

strncpy() memset()s the destination and requires you to do your own, error-prone NULL terminating: it's utter crap; hard to use crap, and inefficient crap--THAT is why people use strcpy() instead of strncpy().

If stuff like strlcpy() and strlcat() had been standardized years ago, we'd be in much better shape then we are now. Yeah, I know, "you can write your own!", but this has been such a big problem, and two little functions do wonders to rectify the situation.

My Uncle Steve
Wednesday, March 31, 2004


I agree, opportunities would still exist. Such as:

char buffer[100];
Object obj;

where Object has virtual methods.

But cases such as this are few; by contrast, every time you declare a string buffer on the stack, there is a potential vulnerability.
Thursday, April 1, 2004

*  Recent Topics

*  Fog Creek Home