mailing list archives
Re: Announcing RSX - non exec stack/heap module
From: Crispin Cowan <crispin () wirex com>
Date: Tue, 12 Jun 2001 17:41:21 -0700
Paul Starzetz wrote:
Crispin Cowan wrote:
It is not very hard to mmap the libc code as non-executable are into
main memory. After the regular programm code jumps into some libc
function, we can check in the gp() handler if the gp fault resulted from
jumping into the libc area by a ret (the target address should still be
on the stack) or by a regular call/jmp instruction.
That's an interesting idea, but the performance penalty will be substantial.
You will pay for (at least) two system calls per library call. In early
StackGuard research, we experimented with hardware protection methods that
imposed 2 syscalls per function call, and the overhead was between 500% and
10,000%, which just isn't realistic for prodution use.
Yes and no! I have written such a code for rsx. The overhead is more
precisely 1x page fault and 1x general protection fault + the emulation
code (jmp/call/ret), which is not equal to 2x syscall + emulation, but
indeed of similar magnitude. However it works.
I presume that what you're doing here is to mark the library pages
non-executable, and then make them executable when you get a page fault due to
some code trying to make a library call. If so, how do you distinguish between
legitmate calls into the library, and bogus calls made by a buffer overflow?
Note that a simpler protection (but maybe not so effective) can be done
by means of ld.so. What does people mean if they talk about
"ret-into-libc" is just a common name for the technique. It is not technically
precise. The general case is to change a function return address so that it
jumps to code that does "exec(sh)". The intructions that do this don't have to
be in libc, and don't have to be in a library, they can be in the program's main
executable body. It's just convenient for the attacker to use libc, because libc
necessarily has "exec(sh)" in it, and most programs link to libc.
Making libc non-executable is effectively another level of obscurity defense. It
makes existing attack scripts break, but can be bypassed in most cases if the
attacker is willing to take the time to find the right sequence of bytes
somewhere in the body of the victim program.
So now assume we doesn't link the libc-plt to the real libc location -
Same effect: you deny the attacker access to the libc code body, forcing them to
look elsewhere for a fairly common sequence of a half dozen bytes in an
Thanks to Solar Designer for pointing out that my previous claim that
non-executable stacks & heaps can "always" be bypassed is inaccurate. They can
often be bypassed, but not always.
Crispin Cowan, Ph.D.
Chief Scientist, WireX Communications, Inc. http://wirex.com
Security Hardened Linux Distribution: http://immunix.org
Available for purchase: http://wirex.com/Products/Immunix/purchase.html