Vulnerability Development mailing list archives

Re: stackguard-like embedded protection


From: antirez <antirez () linuxcare com>
Date: Wed, 8 Jan 1997 09:10:36 +0100

On Fri, Sep 08, 2000 at 12:22:06AM -0700, Crispin Cowan wrote:
... as you say, not reentrant, and therefore not recursive.  Furthermore, you
can't use "safe_enter" and "safe_leave" in more than one function at a time.

Hi Crispin,

yes, this is just an example. I'm releasing a simple header file
that implements this, it's still not-thread safe if you select some
behaviour, anyway once you parsed the code with a perl script (or add
the safe_enter, safe_leave and bla bla by hand) you can compile it with
-DSB_STACKGUARD_LIKE or -DSB_STACKSHIELD_LIKE and so on
(of course even SB_NO_STACKPROTECTION).
In order to implement the stackshield like protection embedded in the code
I used a simple trick that's not so portable but that is ok for i386
and the other arch that stores the RET on the stack. I store a variable
like volatile unsigned char magic[1] at the end so I'll get the RET
with magic[5-6-7-8], now I can store it outside the stack, every time
I enter in a function I store the old return address in order to
allow recursion. This is not a stack smashing solution, I'm coding this
little header and writing my impression in order to hack arround this
for the first time. Maybe, after this didactic work, I'll suggest some
idea.

This is not just a detail; it is a critical issue in designing a stack smashing
defense.  To do integrity checking on the stack, you need to insert canaries
that have these properties:

   * you can decide whether your integrity marks are still intact when you
     return
   * you can do so through a sequence of recursive calls
   * you are not depending on the stack itself to detect these factors (because
     the attacker can corrupt the stack)

Agreed at all: in embedded protections you can usa for example dynamic
memory to store things. It's not fast, but offers the possibility to
mprotect(2) the memory page that can be usefull against some kind of
attacks.

   * totally static canary:  we used the "terminator" hack because we
     conjecture that it is hard for buffer overflows to generate terminator
     symbols
   * load-time static canaries:  we bind values from /dev/random to functions
     at load time
   * use an alternate stack:  StackShield uses this approach.  We also thought
     of that, but discarded it because the first two solutions seemed easier
     than the alternate stack, and we could not find any way in which the
     alternate stack was safer

Yes, in stackguard-like mode one of the approach I'm using is this:

int global_rand;

at program startup:

void stackprotection_init(void)
{
        open /dev/urandom
        get a random number and put it in global_rand
}

int protected(args)
{
        volatile int canary = global_rand;
        volatile int static = 0x000AFF0D;

        foo();

        check_the_canary_integrity
        return;
}

Static canary.

This is really fast. Also you can add the stackguard's RET xor with canary
(but the portability becomes ciritical)

So the provided code is an interesting experiment, but is not practical until
it chooses one of these solutions (or invents a new one) that addresses the
recursive problem in a way that is robust against stack smashing.

Agreed, I'm working on it as experiment just since for now I'm interesting
at this problem. I hope to publish what I'll learn soon.

regards,
antirez

--
Salvatore Sanfilippo, Open Source Developer, Linuxcare Italia spa
+39.049.80 43 411 tel, +39.049.80 43 412 fax
antirez () linuxcare com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.


Current thread: