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>
