[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: protection against buffer overflows



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 to: