Eddies in the Space-Time Continuum
Peter Harvey's blog
Recent entries
Archives
« June 2005 »
MonTueWedThuFriSatSun
  
1
2
3
4
5
6
7
8
9
10
11
12
15
16
17
18
19
20
21
22
23
25
26
29
30
   
       
Today
Click me to subscribe
Search

Twitter

follow peteh at http://twitter.com
Google Reader
Technorati
My tags
aliases announcement birth book brompton children cloud computer croudsourcing damage datamining decision dtrace ethics family fun futurology gapminder geros goalfree goals happiness home human incentives intel internet ipod junk kepner-tregoe knowledge life loft losug mail making management mdb meme methodologies metro mice modelling morals mrgum network nfs nis+ nis_cachemgr nscd opensolaris performance philosophy photo pizza poverty process programming psychology rands review rodents rules security seedcamp sgrt sigbus signals sigsegv smart smf solaris sprcfb squirrels sun sunray superhero system ted teleworking terminal terminfo thinking troubleshooting trust wisdom
Flickr
www.flickr.com
This is a Flickr badge showing public photos from peteh. Make your own badge here.
del.icio.us links
del.icio.us tags
Bookmarks
RSS Feeds
XML
All
/Family
/General
/Internet
/Links
/Mac
/Management
/Palm
/Security
/Solaris
/Sun
Links
 
Licence
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.

Today's Page Hits: 325

« Previous day (Jun 27, 2005) | Main | Next day (Jun 28, 2005) »
Tuesday Jun 28, 2005
Buffer overflows and SPARC register windows (part 2)
In my previous blog entry I wrote:

So it does appear that register windows do offer some protection but I've never managed to demonstrate this with simple overflow code. If anybody has an example to back me up I'd be very interested to try it.
I had a few comments on the entry which spurred me on to writing an example which shows that overwriting the return value on the stack in memory isn't always successful on SPARC. Here it is:

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Example code showing how register windows on SPARC partially save
 * you from buffer overflows. This is *no* defence as this is a
 * contrived example :-)
 */

#include <stdio.h>
#include <dlfcn.h>

/*
 * The SPARC stack layout means you can only overflow into the stack
 * above (ie the caller's stack) - in this case bar(), which will have
 * a return address into main().
 *
 * By compiling this and checking the assembler it was found that the
 * local a[] array was 0x14 bytes below the frame pointer. The return
 * address is 15 words above that. See /usr/include/sys/frame.h for
 * details.
 *
 * The line where we zero the return address (a[i] = 0) should by all
 * accounts cause the program to SEGV on exit. In fact it doesn't as
 * the return address is still stored in a register window.
 *
 * If we want it to SEGV we have to make some function calls from
 * within foo() to 'push' bar()'s frame out of the register window and
 * have it spill onto the stack. Once we've done that then it won't be
 * filled back into the register window until we call restore at the
 * end of this function.
 *
 * To see this in action, simply uncomment the printf() before the
 * return address is zeroed. There is sufficient function depth in
 * the call to printf() to spill bar()'s frame.
 */

void
foo(int x, int y, int z)
{
	Dl_info dli;	/* Used to extract symbol names */
	int a[1], i;

	/* printf("hello, world\n"); */

	i = 20;		/* 0x14 (5 words) to the %fp + 15 words */
	a[i] = 0;	/* Zero the return address */

	printf("Contents of return address in memory are:\n");
	if (dladdr((void *)a[i], &dli) <= 0) {
		printf("%lx\n", a[i]);
	} else {
		printf("%s + 0x%lx\n", dli.dli_sname,
		    (ulong_t)a[i] - (ulong_t)dli.dli_saddr);
	}
}

/*
 * As explained above, we add an extra function call level to make it
 * clearer that the return address is into our program (ie main()).
 */
void
bar()
{
	/*
	 * Add some function arguments that are easy to spot if you
	 * fancy digging around in the stack.
	 */
	foo(0x1234, 0xcafebabe, 0x1234);
}

int
main(int argc, char **argv)
{
	bar();
	return (0);
}

Not the most elegant pieces of code but it's cstyle clean ... in other words, passes Sun's coding style requirements :-)

The main point is that it demonstrates that simply overwriting the return value in memory isn't necessarily sufficient. The register window must have been spilled at some point before this can succeed.


Posted at 04:15PM Jun 28, 2005 by Peter Harvey in Solaris  |  Comments[0]  |  del.icio.us technorati digg