From: Mike Frantzen [frantzen@EXPERT.CC.PURDUE.EDU] Sent: Tuesday, July 25, 2000 8:32 PM To: BUGTRAQ@SECURITYFOCUS.COM Subject: Poor man's solution to format bugs /* * 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 #include #include /* 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); }