[17451] in bugtraq

home help back first fref pref prev next nref lref last post

Re: Future of buffer overflows ?

daemon@ATHENA.MIT.EDU (Gerardo Richarte)
Wed Nov 1 22:11:30 2000

Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id:  <39FE18C4.2A237A6E@core-sdi.com>
Date:         Mon, 30 Oct 2000 21:53:26 -0300
Reply-To: Gerardo Richarte <core.lists.bugtraq@CORE-SDI.COM>
From: Gerardo Richarte <core.lists.bugtraq@CORE-SDI.COM>
To: BUGTRAQ@SECURITYFOCUS.COM

Thomas Dullien wrote:
>
> So it is possible to have readable, non-executable memory pages, at a
> not too bad performance hit of up to 10%. This is very cool.

	This is not a new concept. It's been out there for a while now...

> Does this mean buffer overflows and format string vulnerabilities are
> dead ?

	I'll hung from here.

	As you said, this is not true, it's just a little trickier to
exploit a "return address on the stack" buffer overflow bug.
	You showed us a way to do it (by returning to exec() with "pre
pushed" arguments)

	here I'll show two different approaches to exploit this bugs in
"protected" systems.

	The first approach is simple, it's not too different to what you
described, but will serve as introduction:

	Feed a return address and arguments so the RET "calls" memcpy(),
and use this memcpy() to move the buffer to some place in memory where
you can jump latter. Then tell memcpy() to return to this new place,
clarifying:

	[buffer] &caller		; before overflow

	a standard exploit, with executable stack makes:

	[buffer] &buffer		; returning to buffer

	RET jumps to &buffer

	you described:

	[/bin/sh] &system xxxx &buffer	; calling system("/bin/sh")

	what's this?

	RET jumps to &system, &buffer is the argument for system,
so, this is a perfect and legal system("/bin/sh") without executing any
code in the stack (this requires that you know the address of system...
which doesn't change on the same platform, same libc version, same more
things)

	what's xxxx up there for?
	it's where system() returns, we can use it.

	I said:

	[code] &memcpy &place &place &buffer

	what?

	translated into:

	memcpy(&buffer,&place)
	jmp &place		; place()

	memcpy() copies from buffer to a useful place where you can
write and execute (is there a place like this?), then, it returns
to address on top of the stack: out first &place, jumping to the copy.

	This can be useful in some platform, I don't know, it can be
used (the memcpy()) to overwrite the GOT, or destructors table, etc, etc.


	The second option... let's call it "pop&ret"

	Here I present a way to code any program, or almost any program,
in a way such that it can be fetched into a buffer overflow in a platform
where the stack (and any other place in memory, but libc) is executable:

	Why can't we make more than a call with arguments and a call
without arguments, like in memcpy(), place()?
	The problem is that the arguments for memcpy() are in the stack,
in the place where the return address from place() should be.
	But we can return to better places, this is the idea:


	Almost every function [in libc] ends with:

pop3:
	pop	something
pop2:
	pop	something	; some pops into regs
pop1:
	pop	something
	ret

	or

	pop 	something
	pop 	something	; some pops into regs
	pop 	something
popbp:
	pop	ebp
	mov	esp,ebp
	ret

	suppose we called gets(), that consumes 1 argument, we
can code something like:

	while (1) {
		gets(buffer);
		system(buffer);
	}

	like this:	

[buffer] &gets &pop1 &buffer &system &pop1 &buffer &popbp buffer+BUF_SIZE

	what?

	yes!

	first RET jumps to gets() with &buffer as argument.
	gets() RET jumps to pop1
	pop1 consumes gets() argument from stack and RETs to system
	system's argument is buffer.
	system's RET jumps to pop1, it consumes 1 argument, jumps to popbp
	yeah!
	popbp pops buffer+BUF_SIZE (the address of our first return addr)
	makes esp point to our first return address...
	returns: everything starts again.

	got it?

	you can call functions with more that a single argument by
jumping to pop2 or pop3 (or whatever you need as long as you can find it
in libs... you can look for:

	add	sp,10h
	ret

	if you have to consume too many arguments from the stack)

	actually, this while() {} may or may not work (the stack may
get overwritten by the called function... but the while is not the point,
is it?)

	ok, this is from the top of my head, this code is not tested, it's
not bullet proof, but the method has been tested (and used) successfully in our labs...

	richie

PS: We are preparing an article on [really] Advanced Buffer Overflows,
so... stay tuned!

--
A390 1BBA 2C58 D679 5A71 - 86F9 404F 4B53 3944 C2D0
Investigacion y Desarrollo - CoreLabs - Core SDI
http://www.core-sdi.com

--- For a personal reply use gera@core-sdi.com

home help back first fref pref prev next nref lref last post