[15967] in bugtraq
Poor man's solution to format bugs
daemon@ATHENA.MIT.EDU (Mike Frantzen)
Wed Jul 26 14:52:19 2000
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Message-ID: <200007260031.TAA27965@expert.cc.purdue.edu>
Date: Tue, 25 Jul 2000 19:31:41 -0500
Reply-To: Mike Frantzen <frantzen@EXPERT.CC.PURDUE.EDU>
From: Mike Frantzen <frantzen@EXPERT.CC.PURDUE.EDU>
To: BUGTRAQ@SECURITYFOCUS.COM
/*
* This is a kludgy example of a source level workaround to the now
* infamous format bugs. It should work for newer versions of gcc. Older
* versions should work as well but you can use recursive macros.
*
* It uses a set of variable arguement macros to wrap variable arguement
* functions. It counts the number of arguements and passes the count
* to a wrapper function. Now it has a count of the passed arguements.
*
* It should be relatively easy to apply the technique to other vulnerable
* functions. Care would have to be taken in multithreaded programs to
* use a thread specific data.
* Stick the macros into the standard include's and a slight hack to LD_PRELOAD
* or libc. Those of us who are not Theo get some semblance of protection ;)
*
* I'm sure someone with more sleep will improve on the concept.
*
* See the gcc info pages for an explaination of variable arguement macros.
* I'm too tired to explain them. You may want to run 'gcc -E' against it
* to see how they expand.
*
* gcc -v
* Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/specs
* gcc version 2.95.2 19991024 (release)
*
* Program output:
* none
* one 1
* two 1 2
* three 1 2 3
* Aiieee. Arguement count mismatch of 1.
* Aiieee. Arguement count mismatch of -1.
*
*
* As always, pardon the spelling errors. Bad english is by native language.
* See you all at defcon.
*/
#include <stdio.h>
#include <stdio.h>
#include <varargs.h>
/* Could stick this stuff into an include file */
#define printf mikes_print(&cnt, print0
#define print0(x, args...) x ,print1(## args)
#define print1(x, args...) x+(++cnt-cnt) ,print2(## args)
#define print2(x, args...) x+(++cnt-cnt) ,print3(## args)
#define print3(x, args...) x+(++cnt-cnt) ,print4(## args)
#define print4(x, args...) x+(++cnt-cnt) ,print5(## args)
#define print5(x, args...) x+(++cnt-cnt) ,print6(## args)
#define print6(x, args...) x+(++cnt-cnt) ,print7(## args)
#define print7(x, args...) x+(++cnt-cnt) ,print8(## args)
#define print8(x, args...) x+(++cnt-cnt) ,print9(## args)
#define print9(x, args...) Need_to_make_more_print_statements
/* END include stuff */
void mikes_print(int *args, char *format, ...);
/* Arguement counter */
int cnt = 0;
int main(void)
{
printf("none\n");
printf("one %d\n", 1);
printf("two %d %d\n", 1, 2);
printf("three %d %d %d\n", 1, 2, 3);
printf("explode %x %n %p\n", 1, 2, 3, 4);
printf("explode %d %p %n %d %d\n", 1, 2, 3, 4);
return 0;
}
/*
* Simply counts the % tokens in the function.
* Bomb out if they don't match *args.
*/
void mikes_print(int *args, char *format, ...)
{
va_list ap;
char *rptr;
for (rptr = format; *rptr; rptr++)
if (*rptr == '%')
if (*++rptr != '%')
(*args)--;
if (*args) {
fprintf(stderr, "Aiieee. Arguement count mismatch of %d.\n", *args);
*args = 0;
return;
}
/* Must turn counter back to 0 */
*args = 0;
va_start(ap);
vprintf(format, ap);
va_end(ap);
}