On Fri, Jan 18, 2002 at 09:20:16PM +0100, Vincent wrote:
> Hi all !
> 
> I'm working on buffer overflows these days, and more precisely the possible
> methods to avoid them.
> It seems that the most used tools to prevent exploits based on buffer
> overflows are Libsafe, OpenWall, StackGuard... and maybe Saint Jude.
> 
> Has anyone any interesting comments about theses methods ? 

I would like to comment on another method, if you don't mind. I few
years ago I was after buffer overflows just as you. What I wanted was to
make a programme which parses the C (or whatever) source code and checks
if it is possible a buffer overflow to occur if the programme is fed
suitable input data. The idea was simple:
                1. For each code block (what is put in curly braces
        ("{", "}") in C) check what condition(s) should be met so that
        an overflow occurs.
                2. Then exclude those conditions at which the block is
        not entered at all.
                3. Repeat this procedure until the main () function's
        block is finished.
                4. Do this for all blocks in the source code.
Of course this may be hard to achieve if the, let's say, C code is mixed
with assembler or even machine code; however, it seems applicable for
most "normal" programmes.

A few examples:

/* Fool a programme using the above idea: */

typedef void                    (*VoidFunc) (void);

int main (void)
{
        char                    machine_code [] = "\x00\x01";
        VoidFunc                machine_func = (VoidFunc) machine_code;
        
        machine_func ();
        return (0);
}

/* End of example 1. */



/* Overflow that would be caught: */

#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[])
{
                                        /* Always enered. */
                                        /* argv has argc elements (by
                                           definition). */
        
        char                            *buf;
        unsigned int                    str_len1, str_len2, c;
        
        if ( argc != 3 ) {
                                        /* Entered when argc != 3. */
                return (1);             /* The execution of the enclosing
                                           block is terminated. */
        }
                                        /* Reached when !(argc != 3) <=>
                                           argc == 3. */
        str_len1 = strlen (argv [0]);   /* Overflow when:
                                           1. 0 > argc-1 <=> 0 > 2. */
                                        /* => No overflow. */
        str_len2 = strlen (argv [1]);   /* Overflow when:
                                           1. 1 > argc-1 <=> 1 > 2. */
                                        /* => No overflow. */
        buf = (char*) malloc (sizeof (char) * (str_len1+str_len2));
                                        /* buf has 
                                          (sizeof (char)*(str_len1+str_len2)) /
                                          sizeof (char) ==
                                          (str_len1+str_len2) elements. */
        for ( c = 0; c < str_len1; c++ ) {
                                        /* Entered when c < str_len1. */
                buf [c] = argv [0][c];  /* Overflow when:
                                           1. c >= (str_len1+str_len2)
                                           2. 0 > argc-1 <=> 0 > 2.
                                           3. c > strlen (argv [0]) <=>
                                              c > str_len1. */
                                        /* => No overflow. */
        }
                                        /* Reached when c == str_len1. */
        for ( c = 0; c < str_len2; c++ ) {
                                        /* Entered when c < str_len2. */
                buf [c+str_len1] = argv [1][c];
                                        /* Overflow when:
                                           1. c+str_len1 >= (str_len1+str_len2)
                                              <=> c >= str_len2.
                                           2. 1 > argc-1 <=> 1 > 2.
                                           3. c > strlen (argv [1]) <=>
                                              c > str_len2. */
                                        /* => No overflow. */
        }
                                        /* Reached when c == str_len2. */
        buf [c+str_len1] = '\0';        /* Overflow when:
                                           1. c+str_len1 >= (str_len1+str_len2)
                                              <=> c >= str_len2 */
                                        /* => Overflow, because of 1. */
        return (0);                     /* End of processing. */
}

/* End of example 2. */

I have wasted so much of your time in the hope that someone might get
interested and volunteer for creating such a tool. I myself gave up
before finishing even the C parser, since I was on my own and the
project required kilobytes of code.

Thanks, and sorry for the time I took,
-- 
Pav

Reply via email to