Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Feb 1997 14:48:06 +1000 (EST)
From:      Stephen McKay <syssgm@devetir.qld.gov.au>
To:        Charles Mott <cmott@srv.net>
Cc:        freebsd-chat@freebsd.org, syssgm@devetir.qld.gov.au
Subject:   Re: Trying to understand stack overflow
Message-ID:  <199702140448.OAA27909@ogre.devetir.qld.gov.au>

next in thread | raw e-mail | index | archive | help

Charles Mott <cmott@srv.net> wrote:

>> >If it does, then it would be interesting to have a version of gcc which 
>> >adds some "noise" as to where exactly in the stack an automatic variable 
>> >is located.  
>> 
>> Yes, I wondered about this too. I don't believe the actual location of
>> an auto makes any difference, because the desired effect is to overwrite
>> the return address. 
>
>How does control flow fall through to the overflow part of the stack?  If
>an absolute return address is given, I don't see how this can be done. 
>There is something about the stack mechanism I need to understand. 

Stack grows downward on the 386 architecture.  You get something like
this for a frame:

	| ...            |   High addresses
	+----------------+
	| fn argument 2  |
	+----------------+
	| fn argument 1  |
	+----------------+
	| return address |
	+----------------+
	| previous frame |  <- %ebp = frame pointer
	+----------------+
	| local          |
	|   variables    |
	+----------------+  <- %esp = stack pointer
	| ...            |
			     Low addresses

The function arguments are pushed onto the stack in reverse order, then the
actual call instruction pushes the return address.  The function preamble
pushes the frame pointer and decrements the stack pointer to make enough
space for local variables.  The first fn argument is at 8(%ebp), the second
at 12(%ebp) and the first local is at -4(%ebp), assuming they are integers.
Ignore register variables for the moment; the 386 has so few anyway.

Now, if one of those local variables is an array that you can overflow,
the stuff that will get overwritten includes all the local variables with
higher addresses plus the saved frame pointer plus the return address.
If you carefully manipulate the return address you can run code from the
same array you overflowed.  Generally you would spawn /bin/sh reading
from stdin, and then pump arbitrary shell commands at it.

>> >Would it also be possible to have separate data and control flow
>> >stacks? 
>> 
>> Yes that would also make more sense.
>
>Any advice here on how to do this would be appreciated.  If there is a
>conceptual reason it won't work -- no spare registers, or possibly
>interference with custom assembler code -- I would appreciate knowing.  I
>just need to find a lousy x386 reference (either online or printed). 

The real problem here is lack of bounds checking on memory objects.  I
remember Dennis Ritchie (hmm, or was it Ken T?) claim that he had modified
his system C compiler so that every C pointer implied length as well as
starting location.  Thus, every pointer and array access could be checked
for illegitimate accesses.  The penalty is doubling the size of every pointer
plus a run time checking cost.  Given the dramas people are having with
security nowadays, and the plummeting cost of RAM and CPU power, I think
such an option should be added to GCC with all speed.  It can be done, if
you think about it a bit.  If I could read GNU Standard C, I might even
do it myself. :-)	[GNU indenting advocates may throw tomatoes now].

Stephen.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702140448.OAA27909>